summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlain Frisch <alain@frisch.fr>2014-08-07 16:07:55 +0000
committerAlain Frisch <alain@frisch.fr>2014-08-07 16:07:55 +0000
commit50f47df33a6061e1acd015dbb0dcffcdd51e0f2f (patch)
tree568e704c3ff8e8e055573cc44efa4d522b0341f1
parent9e23ded0d195e861ad9ed7d0801ed1c3a0ed34e3 (diff)
parent047e09748c91e1d8f80b51edfc33de76fbfc57da (diff)
downloadocaml-50f47df33a6061e1acd015dbb0dcffcdd51e0f2f.tar.gz
Sync with trunk. Rebinding of inlined extension constructors with free variables is not yet supported.
git-svn-id: http://caml.inria.fr/svn/ocaml/branches/constructors_with_record3@15069 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--.depend284
-rw-r--r--.gitignore2590
-rw-r--r--.travis-ci.sh19
-rw-r--r--.travis.yml4
-rw-r--r--Changes240
-rw-r--r--INSTALL5
-rw-r--r--Makefile39
-rw-r--r--Makefile.nt22
-rw-r--r--VERSION2
-rw-r--r--asmcomp/.ignore1
-rw-r--r--asmcomp/CSEgen.ml322
-rw-r--r--asmcomp/CSEgen.mli38
-rw-r--r--asmcomp/amd64/CSE.ml39
-rw-r--r--asmcomp/amd64/arch.ml16
-rw-r--r--asmcomp/amd64/emit.mlp23
-rw-r--r--asmcomp/amd64/emit_nt.mlp45
-rw-r--r--asmcomp/amd64/proc.ml19
-rw-r--r--asmcomp/amd64/selection.ml14
-rw-r--r--asmcomp/arm/CSE.ml38
-rw-r--r--asmcomp/arm/emit.mlp30
-rw-r--r--asmcomp/arm/proc.ml24
-rw-r--r--asmcomp/arm64/CSE.ml38
-rw-r--r--asmcomp/arm64/emit.mlp19
-rw-r--r--asmcomp/arm64/proc.ml18
-rw-r--r--asmcomp/asmgen.ml3
-rw-r--r--asmcomp/asmlink.ml62
-rw-r--r--asmcomp/asmlink.mli5
-rw-r--r--asmcomp/asmpackager.ml7
-rw-r--r--asmcomp/asmpackager.mli2
-rw-r--r--asmcomp/clambda.ml70
-rw-r--r--asmcomp/clambda.mli15
-rw-r--r--asmcomp/closure.ml374
-rw-r--r--asmcomp/closure.mli1
-rw-r--r--asmcomp/cmm.ml6
-rw-r--r--asmcomp/cmm.mli6
-rw-r--r--asmcomp/cmmgen.ml40
-rw-r--r--asmcomp/cmx_format.mli9
-rw-r--r--asmcomp/compilenv.ml19
-rw-r--r--asmcomp/compilenv.mli4
-rw-r--r--asmcomp/deadcode.ml67
-rw-r--r--asmcomp/deadcode.mli16
-rw-r--r--asmcomp/emitaux.ml17
-rw-r--r--asmcomp/emitaux.mli7
-rw-r--r--asmcomp/i386/CSE.ml48
-rw-r--r--asmcomp/i386/arch.ml23
-rw-r--r--asmcomp/i386/emit.mlp23
-rw-r--r--asmcomp/i386/emit_nt.mlp45
-rw-r--r--asmcomp/i386/proc.ml26
-rw-r--r--asmcomp/i386/selection.ml16
-rw-r--r--asmcomp/linearize.ml54
-rw-r--r--asmcomp/linearize.mli1
-rw-r--r--asmcomp/liveness.ml53
-rw-r--r--asmcomp/liveness.mli1
-rw-r--r--asmcomp/mach.ml4
-rw-r--r--asmcomp/mach.mli7
-rw-r--r--asmcomp/power/CSE.ml38
-rw-r--r--asmcomp/power/emit.mlp19
-rw-r--r--asmcomp/power/proc.ml15
-rw-r--r--asmcomp/power/scheduling.ml2
-rw-r--r--asmcomp/printclambda.ml17
-rw-r--r--asmcomp/printcmm.ml6
-rw-r--r--asmcomp/printmach.ml7
-rw-r--r--asmcomp/proc.mli6
-rw-r--r--asmcomp/reg.ml10
-rw-r--r--asmcomp/reg.mli1
-rw-r--r--asmcomp/schedgen.ml39
-rw-r--r--asmcomp/schedgen.mli2
-rw-r--r--asmcomp/selectgen.ml18
-rw-r--r--asmcomp/selectgen.mli5
-rw-r--r--asmcomp/sparc/CSE.ml31
-rw-r--r--asmcomp/sparc/emit.mlp14
-rw-r--r--asmcomp/sparc/proc.ml13
-rw-r--r--asmcomp/spill.ml15
-rw-r--r--asmcomp/spill.mli1
-rw-r--r--asmcomp/split.ml7
-rw-r--r--asmcomp/split.mli2
-rw-r--r--asmrun/.depend1266
-rw-r--r--asmrun/Makefile2
-rw-r--r--asmrun/arm64.S2
-rw-r--r--asmrun/backtrace.c88
-rw-r--r--asmrun/fail.c5
-rw-r--r--asmrun/i386.S15
-rw-r--r--asmrun/natdynlink.c5
-rw-r--r--asmrun/signals_osdep.h3
-rw-r--r--asmrun/stack.h2
-rwxr-xr-xboot/ocamlcbin1544162 -> 1706814 bytes
-rwxr-xr-xboot/ocamldepbin424799 -> 524020 bytes
-rwxr-xr-xboot/ocamllexbin183945 -> 250275 bytes
-rw-r--r--bytecomp/bytegen.ml60
-rw-r--r--bytecomp/bytegen.mli1
-rw-r--r--bytecomp/bytelibrarian.ml7
-rw-r--r--bytecomp/bytelibrarian.mli2
-rw-r--r--bytecomp/bytelink.ml51
-rw-r--r--bytecomp/bytelink.mli3
-rw-r--r--bytecomp/bytepackager.ml26
-rw-r--r--bytecomp/bytepackager.mli3
-rw-r--r--bytecomp/bytesections.ml12
-rw-r--r--bytecomp/bytesections.mli2
-rw-r--r--bytecomp/cmo_format.mli3
-rw-r--r--bytecomp/dll.ml6
-rw-r--r--bytecomp/dll.mli2
-rw-r--r--bytecomp/emitcode.ml10
-rw-r--r--bytecomp/emitcode.mli4
-rw-r--r--bytecomp/lambda.ml30
-rw-r--r--bytecomp/lambda.mli9
-rw-r--r--bytecomp/matching.ml92
-rw-r--r--bytecomp/meta.ml10
-rw-r--r--bytecomp/meta.mli10
-rw-r--r--bytecomp/printlambda.ml3
-rw-r--r--bytecomp/simplif.ml2
-rw-r--r--bytecomp/symtable.ml9
-rw-r--r--bytecomp/symtable.mli6
-rw-r--r--bytecomp/translclass.ml8
-rw-r--r--bytecomp/translcore.ml62
-rw-r--r--bytecomp/translmod.ml133
-rw-r--r--bytecomp/translmod.mli2
-rw-r--r--bytecomp/translobj.ml11
-rw-r--r--bytecomp/translobj.mli2
-rw-r--r--byterun/.depend565
-rwxr-xr-xbyterun/Makefile.common7
-rw-r--r--byterun/alloc.c6
-rw-r--r--byterun/array.c8
-rw-r--r--byterun/backtrace.c266
-rw-r--r--byterun/extern.c8
-rw-r--r--byterun/fail.c8
-rw-r--r--byterun/fix_code.c6
-rw-r--r--byterun/hash.c15
-rw-r--r--byterun/instruct.h7
-rw-r--r--byterun/interp.c33
-rw-r--r--byterun/major_gc.c35
-rw-r--r--byterun/memory.h16
-rw-r--r--byterun/misc.c1
-rw-r--r--byterun/misc.h2
-rw-r--r--byterun/obj.c4
-rw-r--r--byterun/startup.c4
-rwxr-xr-xconfigure33
-rw-r--r--debugger/.depend6
-rw-r--r--debugger/Makefile.shared2
-rw-r--r--debugger/debugcom.ml6
-rw-r--r--debugger/input_handling.mli2
-rw-r--r--debugger/program_management.ml2
-rw-r--r--debugger/source.ml2
-rw-r--r--driver/compenv.ml20
-rw-r--r--driver/compenv.mli3
-rw-r--r--driver/compile.ml18
-rw-r--r--driver/compmisc.ml20
-rw-r--r--driver/main.ml9
-rw-r--r--driver/main_args.ml268
-rw-r--r--driver/main_args.mli204
-rw-r--r--driver/optcompile.ml16
-rw-r--r--driver/optmain.ml10
-rw-r--r--driver/pparse.ml54
-rw-r--r--driver/pparse.mli8
-rw-r--r--lex/Makefile2
-rw-r--r--lex/common.ml2
-rw-r--r--man/ocaml.m23
-rw-r--r--man/ocamlc.m32
-rw-r--r--man/ocamlopt.m30
-rw-r--r--ocamlbuild/Makefile7
-rw-r--r--ocamlbuild/Makefile.noboot2
-rw-r--r--ocamlbuild/display.ml18
-rw-r--r--ocamlbuild/main.ml39
-rw-r--r--ocamlbuild/my_std.ml27
-rw-r--r--ocamlbuild/my_unix.ml4
-rw-r--r--ocamlbuild/ocaml_specific.ml5
-rw-r--r--ocamlbuild/ocamlbuild_executor.ml38
-rw-r--r--ocamlbuild/options.ml2
-rw-r--r--ocamlbuild/testsuite/internal.ml13
-rw-r--r--ocamldoc/.depend86
-rw-r--r--ocamldoc/Makefile3
-rw-r--r--ocamldoc/Makefile.nt1
-rw-r--r--ocamldoc/generators/odoc_todo.ml8
-rw-r--r--ocamldoc/odoc_analyse.ml25
-rw-r--r--ocamldoc/odoc_ast.ml231
-rw-r--r--ocamldoc/odoc_ast.mli15
-rw-r--r--ocamldoc/odoc_cross.ml68
-rw-r--r--ocamldoc/odoc_dep.ml10
-rw-r--r--ocamldoc/odoc_env.ml18
-rw-r--r--ocamldoc/odoc_env.mli6
-rw-r--r--ocamldoc/odoc_exception.ml1
-rw-r--r--ocamldoc/odoc_extension.ml46
-rw-r--r--ocamldoc/odoc_html.ml194
-rw-r--r--ocamldoc/odoc_info.ml8
-rw-r--r--ocamldoc/odoc_info.mli87
-rw-r--r--ocamldoc/odoc_latex.ml236
-rw-r--r--ocamldoc/odoc_man.ml464
-rw-r--r--ocamldoc/odoc_merge.ml84
-rw-r--r--ocamldoc/odoc_messages.ml11
-rw-r--r--ocamldoc/odoc_misc.ml8
-rw-r--r--ocamldoc/odoc_module.ml24
-rw-r--r--ocamldoc/odoc_scan.ml22
-rw-r--r--ocamldoc/odoc_search.ml76
-rw-r--r--ocamldoc/odoc_search.mli25
-rw-r--r--ocamldoc/odoc_sig.ml192
-rw-r--r--ocamldoc/odoc_sig.mli16
-rw-r--r--ocamldoc/odoc_str.ml236
-rw-r--r--ocamldoc/odoc_str.mli7
-rw-r--r--ocamldoc/odoc_test.ml5
-rw-r--r--ocamldoc/odoc_texi.ml114
-rw-r--r--ocamldoc/odoc_text.ml1
-rw-r--r--ocamldoc/odoc_text_lexer.mll18
-rw-r--r--ocamldoc/odoc_text_parser.mly2
-rw-r--r--ocamldoc/odoc_to_text.ml51
-rw-r--r--ocamldoc/odoc_type.ml13
-rw-r--r--ocamldoc/odoc_types.ml1
-rw-r--r--ocamldoc/odoc_types.mli1
-rw-r--r--otherlibs/Makefile.shared2
-rw-r--r--otherlibs/bigarray/.depend30
-rw-r--r--otherlibs/bigarray/mmap_unix.c4
-rw-r--r--otherlibs/dynlink/Makefile3
-rw-r--r--otherlibs/dynlink/dynlink.ml55
-rw-r--r--otherlibs/dynlink/natdynlink.ml59
-rw-r--r--otherlibs/graph/.depend160
-rw-r--r--otherlibs/graph/libgraph.h3
-rw-r--r--otherlibs/num/.depend20
-rw-r--r--otherlibs/num/big_int.ml22
-rw-r--r--otherlibs/num/big_int.mli2
-rw-r--r--otherlibs/num/nat.ml23
-rw-r--r--otherlibs/num/ratio.ml51
-rw-r--r--otherlibs/str/.depend10
-rw-r--r--otherlibs/str/str.ml54
-rw-r--r--otherlibs/systhreads/.depend20
-rw-r--r--otherlibs/systhreads/Makefile2
-rw-r--r--otherlibs/systhreads/threadUnix.ml6
-rw-r--r--otherlibs/systhreads/threadUnix.mli25
-rw-r--r--otherlibs/threads/.depend20
-rw-r--r--otherlibs/threads/Makefile4
-rw-r--r--otherlibs/threads/marshal.ml30
-rw-r--r--otherlibs/threads/pervasives.ml105
-rw-r--r--otherlibs/threads/threadUnix.ml7
-rw-r--r--otherlibs/threads/threadUnix.mli25
-rw-r--r--otherlibs/threads/unix.ml42
-rw-r--r--otherlibs/unix/.depend804
-rw-r--r--otherlibs/unix/unix.ml43
-rw-r--r--otherlibs/unix/unix.mli50
-rw-r--r--otherlibs/unix/unixLabels.mli54
-rw-r--r--otherlibs/win32unix/unix.ml40
-rw-r--r--parsing/ast_helper.ml124
-rw-r--r--parsing/ast_helper.mli137
-rw-r--r--parsing/ast_mapper.ml253
-rw-r--r--parsing/ast_mapper.mli32
-rw-r--r--parsing/lexer.mll20
-rw-r--r--parsing/location.ml21
-rw-r--r--parsing/location.mli5
-rw-r--r--parsing/parser.mly209
-rw-r--r--parsing/parsetree.mli70
-rw-r--r--parsing/pprintast.ml118
-rw-r--r--parsing/pprintast.mli12
-rw-r--r--parsing/printast.ml102
-rw-r--r--stdlib/.depend171
-rwxr-xr-xstdlib/Compflags7
-rwxr-xr-xstdlib/Makefile.shared14
-rw-r--r--stdlib/StdlibModules2
-rw-r--r--stdlib/buffer.ml50
-rw-r--r--stdlib/buffer.mli33
-rw-r--r--stdlib/bytes.ml226
-rw-r--r--stdlib/bytes.mli238
-rw-r--r--stdlib/bytesLabels.ml16
-rw-r--r--stdlib/bytesLabels.mli208
-rw-r--r--stdlib/camlinternalFormat.ml2610
-rw-r--r--stdlib/camlinternalFormat.mli98
-rw-r--r--stdlib/camlinternalFormatBasics.ml614
-rw-r--r--stdlib/camlinternalFormatBasics.mli287
-rw-r--r--stdlib/digest.ml25
-rw-r--r--stdlib/digest.mli10
-rw-r--r--stdlib/format.ml488
-rw-r--r--stdlib/gc.mli2
-rw-r--r--stdlib/genlex.ml16
-rw-r--r--stdlib/lexing.ml47
-rw-r--r--stdlib/lexing.mli10
-rw-r--r--stdlib/map.mli20
-rw-r--r--stdlib/marshal.ml26
-rw-r--r--stdlib/marshal.mli97
-rw-r--r--stdlib/obj.ml29
-rw-r--r--stdlib/obj.mli11
-rw-r--r--stdlib/pervasives.ml95
-rw-r--r--stdlib/pervasives.mli86
-rw-r--r--stdlib/printexc.ml100
-rw-r--r--stdlib/printexc.mli158
-rw-r--r--stdlib/printf.ml751
-rw-r--r--stdlib/printf.mli73
-rw-r--r--stdlib/scanf.ml1041
-rw-r--r--stdlib/scanf.mli10
-rw-r--r--stdlib/set.mli21
-rw-r--r--stdlib/stdLabels.ml2
-rw-r--r--stdlib/stdLabels.mli6
-rw-r--r--stdlib/stream.ml19
-rw-r--r--stdlib/stream.mli3
-rw-r--r--stdlib/string.ml221
-rw-r--r--stdlib/string.mli148
-rw-r--r--stdlib/stringLabels.mli139
-rw-r--r--stdlib/sys.mli2
-rw-r--r--testsuite/external/.ignore2
-rw-r--r--testsuite/external/Makefile91
-rw-r--r--testsuite/external/camlp5-git.patch12
-rw-r--r--testsuite/makefiles/Makefile.common2
-rw-r--r--testsuite/tests/asmcomp/lexcmm.mll14
-rw-r--r--testsuite/tests/asmcomp/parsecmm.mly4
-rw-r--r--testsuite/tests/asmcomp/sparc.S6
-rw-r--r--testsuite/tests/backtrace/Makefile3
-rw-r--r--testsuite/tests/backtrace/backtrace_deprecated.ml50
-rw-r--r--testsuite/tests/backtrace/backtrace_deprecated.reference27
-rw-r--r--testsuite/tests/backtrace/backtrace_slots.ml72
-rw-r--r--testsuite/tests/backtrace/backtrace_slots.reference27
-rw-r--r--testsuite/tests/basic-io-2/io.ml6
-rw-r--r--testsuite/tests/basic-more/pr2719.ml17
-rw-r--r--testsuite/tests/basic-more/pr2719.reference4
-rw-r--r--testsuite/tests/basic-more/tprintf.ml11
-rw-r--r--testsuite/tests/basic/constprop.ml72
-rw-r--r--testsuite/tests/basic/constprop.mlp130
-rw-r--r--testsuite/tests/basic/constprop.reference10
-rw-r--r--testsuite/tests/basic/tailcalls.ml11
-rw-r--r--testsuite/tests/basic/tailcalls.reference1
-rw-r--r--testsuite/tests/embedded/cmcaml.ml2
-rw-r--r--testsuite/tests/formats-transition/Makefile3
-rw-r--r--testsuite/tests/formats-transition/deprecated_unsigned_printers.ml22
-rw-r--r--testsuite/tests/formats-transition/deprecated_unsigned_printers.ml.reference7
-rw-r--r--testsuite/tests/formats-transition/ignored_scan_counters.ml30
-rw-r--r--testsuite/tests/formats-transition/ignored_scan_counters.ml.reference14
-rw-r--r--testsuite/tests/formats-transition/legacy_incompatible_flags.ml20
-rw-r--r--testsuite/tests/formats-transition/legacy_unfinished_modifiers.ml18
-rw-r--r--testsuite/tests/formats-transition/legacy_unfinished_modifiers.ml.reference6
-rw-r--r--testsuite/tests/gc-roots/globrootsprim.c12
-rw-r--r--testsuite/tests/lib-format/Makefile6
-rw-r--r--testsuite/tests/lib-marshal/intext.ml44
-rw-r--r--testsuite/tests/lib-printf/Makefile5
-rw-r--r--testsuite/tests/lib-printf/tprintf.ml251
-rw-r--r--testsuite/tests/lib-printf/tprintf.reference88
-rw-r--r--testsuite/tests/lib-scanf/tscanf.ml4
-rw-r--r--testsuite/tests/match-exception-warnings/Makefile15
-rw-r--r--testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml12
-rw-r--r--testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml.reference11
-rw-r--r--testsuite/tests/match-exception/Makefile15
-rw-r--r--testsuite/tests/match-exception/allocation.ml24
-rw-r--r--testsuite/tests/match-exception/allocation.reference1
-rw-r--r--testsuite/tests/match-exception/exception_propagation.ml17
-rw-r--r--testsuite/tests/match-exception/exception_propagation.reference1
-rw-r--r--testsuite/tests/match-exception/match_failure.ml19
-rw-r--r--testsuite/tests/match-exception/match_failure.reference1
-rw-r--r--testsuite/tests/match-exception/nested_handlers.ml45
-rw-r--r--testsuite/tests/match-exception/nested_handlers.reference1
-rw-r--r--testsuite/tests/match-exception/raise_from_success_continuation.ml15
-rw-r--r--testsuite/tests/match-exception/raise_from_success_continuation.reference2
-rw-r--r--testsuite/tests/match-exception/streams.ml37
-rw-r--r--testsuite/tests/match-exception/streams.reference1
-rw-r--r--testsuite/tests/match-exception/tail_calls.ml21
-rw-r--r--testsuite/tests/match-exception/tail_calls.reference1
-rw-r--r--testsuite/tests/regression/pr5757/pr5757.ml2
-rw-r--r--testsuite/tests/regression/pr6024/Makefile5
-rw-r--r--testsuite/tests/tool-ocamldoc/odoc_test.ml14
-rw-r--r--testsuite/tests/tool-ocamldoc/t01.ml3
-rw-r--r--testsuite/tests/tool-ocamldoc/t01.reference5
-rw-r--r--testsuite/tests/typing-extensions/Makefile4
-rw-r--r--testsuite/tests/typing-extensions/cast.ml96
-rw-r--r--testsuite/tests/typing-extensions/cast.ml.reference33
-rw-r--r--testsuite/tests/typing-extensions/extensions.ml321
-rw-r--r--testsuite/tests/typing-extensions/extensions.ml.reference131
-rw-r--r--testsuite/tests/typing-extensions/msg.ml131
-rw-r--r--testsuite/tests/typing-extensions/msg.ml.reference23
-rw-r--r--testsuite/tests/typing-extensions/open_types.ml109
-rw-r--r--testsuite/tests/typing-extensions/open_types.ml.reference83
-rw-r--r--testsuite/tests/typing-gadts/pr6174.ml.principal.reference9
-rw-r--r--testsuite/tests/typing-gadts/pr6174.ml.reference9
-rw-r--r--testsuite/tests/typing-gadts/test.ml8
-rw-r--r--testsuite/tests/typing-gadts/test.ml.principal.reference6
-rw-r--r--testsuite/tests/typing-gadts/test.ml.reference6
-rw-r--r--testsuite/tests/typing-modules/Test.ml5
-rw-r--r--testsuite/tests/typing-modules/Test.ml.principal.reference5
-rw-r--r--testsuite/tests/typing-modules/Test.ml.reference5
-rw-r--r--testsuite/tests/typing-modules/aliases.ml16
-rw-r--r--testsuite/tests/typing-modules/aliases.ml.reference3
-rw-r--r--testsuite/tests/typing-objects/Tests.ml.principal.reference16
-rw-r--r--testsuite/tests/typing-objects/Tests.ml.reference16
-rw-r--r--testsuite/tests/typing-objects/pr6383.ml1
-rw-r--r--testsuite/tests/typing-objects/pr6383.ml.reference6
-rw-r--r--testsuite/tests/typing-warnings/coercions.ml.principal.reference4
-rw-r--r--testsuite/tests/typing-warnings/coercions.ml.reference4
-rw-r--r--testsuite/typing1
-rw-r--r--tools/.depend14
-rw-r--r--tools/Makefile.shared8
-rwxr-xr-xtools/check-typo19
-rwxr-xr-xtools/ci-build159
-rw-r--r--tools/cmt2annot.ml8
-rw-r--r--tools/depend.ml58
-rw-r--r--tools/dumpobj.ml8
-rwxr-xr-xtools/make-version-header.sh20
-rw-r--r--tools/objinfo.ml54
-rw-r--r--tools/ocamlcp.ml10
-rw-r--r--tools/ocamldep.ml38
-rw-r--r--tools/ocamlmklib.ml10
-rw-r--r--tools/ocamloptp.ml11
-rw-r--r--tools/ocamlprof.ml15
-rw-r--r--tools/profiling.ml2
-rw-r--r--tools/read_cmt.ml11
-rw-r--r--tools/tast_iter.ml54
-rw-r--r--tools/tast_iter.mli4
-rw-r--r--tools/untypeast.ml129
-rw-r--r--toplevel/expunge.ml2
-rw-r--r--toplevel/genprintval.ml79
-rw-r--r--toplevel/opttoploop.ml5
-rw-r--r--toplevel/opttoploop.mli2
-rw-r--r--toplevel/opttopmain.ml1
-rw-r--r--toplevel/topdirs.ml167
-rw-r--r--toplevel/toploop.ml62
-rw-r--r--toplevel/toploop.mli5
-rw-r--r--toplevel/topmain.ml5
-rw-r--r--typing/btype.ml37
-rw-r--r--typing/btype.mli7
-rw-r--r--typing/cmi_format.ml8
-rw-r--r--typing/cmi_format.mli2
-rw-r--r--typing/cmt_format.ml8
-rw-r--r--typing/cmt_format.mli2
-rw-r--r--typing/ctype.ml145
-rw-r--r--typing/ctype.mli5
-rw-r--r--typing/datarepr.ml61
-rw-r--r--typing/datarepr.mli5
-rw-r--r--typing/env.ml174
-rw-r--r--typing/env.mli22
-rw-r--r--typing/envaux.ml6
-rw-r--r--typing/includecore.ml50
-rw-r--r--typing/includecore.mli4
-rw-r--r--typing/includemod.ml53
-rw-r--r--typing/includemod.mli7
-rw-r--r--typing/mtype.ml27
-rw-r--r--typing/oprint.ml147
-rw-r--r--typing/oprint.mli1
-rw-r--r--typing/outcometree.mli26
-rw-r--r--typing/parmatch.ml148
-rw-r--r--typing/predef.ml61
-rw-r--r--typing/predef.mli9
-rw-r--r--typing/printtyp.ml75
-rw-r--r--typing/printtyp.mli8
-rw-r--r--typing/printtyped.ml99
-rw-r--r--typing/subst.ml30
-rw-r--r--typing/subst.mli6
-rw-r--r--typing/typeclass.ml57
-rw-r--r--typing/typeclass.mli2
-rw-r--r--typing/typecore.ml582
-rw-r--r--typing/typecore.mli7
-rw-r--r--typing/typedecl.ml558
-rw-r--r--typing/typedecl.mli19
-rw-r--r--typing/typedtree.ml55
-rw-r--r--typing/typedtree.mli55
-rw-r--r--typing/typedtreeIter.ml87
-rw-r--r--typing/typedtreeIter.mli4
-rw-r--r--typing/typedtreeMap.ml139
-rw-r--r--typing/typedtreeMap.mli10
-rw-r--r--typing/typemod.ml231
-rw-r--r--typing/typemod.mli12
-rw-r--r--typing/types.ml28
-rw-r--r--typing/types.mli30
-rw-r--r--typing/typetexp.ml227
-rw-r--r--typing/typetexp.mli19
-rw-r--r--utils/clflags.ml4
-rw-r--r--utils/clflags.mli6
-rw-r--r--utils/config.mlp12
-rw-r--r--utils/consistbl.ml15
-rw-r--r--utils/consistbl.mli7
-rw-r--r--utils/misc.ml39
-rw-r--r--utils/misc.mli9
-rw-r--r--utils/warnings.ml40
-rw-r--r--utils/warnings.mli5
-rw-r--r--yacc/defs.h44
-rw-r--r--yacc/main.c20
464 files changed, 21177 insertions, 8359 deletions
diff --git a/.depend b/.depend
index f0ecc73c2c..a8b99a9b0d 100644
--- a/.depend
+++ b/.depend
@@ -1,4 +1,4 @@
-putils/ccomp.cmi :
+utils/ccomp.cmi :
utils/clflags.cmi :
utils/config.cmi :
utils/consistbl.cmi :
@@ -44,10 +44,12 @@ parsing/ast_helper.cmo : parsing/parsetree.cmi parsing/longident.cmi \
parsing/ast_helper.cmx : parsing/parsetree.cmi parsing/longident.cmx \
parsing/location.cmx parsing/asttypes.cmi parsing/ast_helper.cmi
parsing/ast_mapper.cmo : parsing/parsetree.cmi utils/misc.cmi \
- parsing/location.cmi utils/config.cmi parsing/ast_helper.cmi \
+ parsing/longident.cmi parsing/location.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/location.cmx utils/config.cmx parsing/ast_helper.cmx \
+ parsing/longident.cmx parsing/location.cmx utils/config.cmx \
+ utils/clflags.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \
parsing/ast_mapper.cmi
parsing/lexer.cmo : utils/warnings.cmi parsing/parser.cmi utils/misc.cmi \
parsing/location.cmi parsing/lexer.cmi
@@ -134,23 +136,23 @@ typing/typedtree.cmi : typing/types.cmi typing/primitive.cmi typing/path.cmi \
typing/ident.cmi typing/env.cmi parsing/asttypes.cmi
typing/typedtreeIter.cmi : typing/typedtree.cmi parsing/asttypes.cmi
typing/typedtreeMap.cmi : typing/typedtree.cmi
-typing/typemod.cmi : typing/types.cmi typing/typedtree.cmi \
+typing/typemod.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \
parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
- typing/includemod.cmi typing/ident.cmi typing/env.cmi
+ typing/includemod.cmi typing/ident.cmi typing/env.cmi \
+ parsing/asttypes.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.cmi : utils/warnings.cmi typing/types.cmi \
- typing/typedtree.cmi typing/path.cmi parsing/parsetree.cmi \
- parsing/longident.cmi parsing/location.cmi typing/env.cmi \
- parsing/asttypes.cmi
+typing/typetexp.cmi : typing/types.cmi typing/typedtree.cmi typing/path.cmi \
+ parsing/parsetree.cmi parsing/longident.cmi parsing/location.cmi \
+ typing/env.cmi parsing/asttypes.cmi parsing/ast_mapper.cmi
typing/btype.cmo : typing/types.cmi typing/path.cmi utils/misc.cmi \
typing/ident.cmi typing/btype.cmi
typing/btype.cmx : typing/types.cmx typing/path.cmx utils/misc.cmx \
typing/ident.cmx typing/btype.cmi
-typing/cmi_format.cmo : typing/types.cmi utils/misc.cmi parsing/location.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 utils/misc.cmx parsing/location.cmx \
+typing/cmi_format.cmx : typing/types.cmx parsing/location.cmx \
utils/config.cmx typing/cmi_format.cmi
typing/cmt_format.cmo : typing/types.cmi typing/typedtreeMap.cmi \
typing/typedtree.cmi utils/misc.cmi parsing/location.cmi \
@@ -168,12 +170,12 @@ typing/ctype.cmx : typing/types.cmx typing/subst.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/datarepr.cmo : typing/types.cmi typing/predef.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/predef.cmx typing/path.cmx \
- parsing/location.cmx typing/ident.cmx typing/btype.cmx \
- parsing/asttypes.cmi typing/datarepr.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.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 \
@@ -207,15 +209,17 @@ typing/includecore.cmx : typing/types.cmx typing/typedtree.cmx \
typing/env.cmx typing/ctype.cmx typing/btype.cmx parsing/asttypes.cmi \
typing/includecore.cmi
typing/includemod.cmo : typing/types.cmi typing/typedtree.cmi utils/tbl.cmi \
- typing/subst.cmi typing/printtyp.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 typing/includemod.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 \
+ typing/includemod.cmi
typing/includemod.cmx : typing/types.cmx typing/typedtree.cmx utils/tbl.cmx \
- typing/subst.cmx typing/printtyp.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 typing/includemod.cmi
+ 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 \
+ typing/includemod.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 \
@@ -231,15 +235,15 @@ typing/oprint.cmx : typing/outcometree.cmi parsing/asttypes.cmi \
typing/parmatch.cmo : utils/warnings.cmi typing/types.cmi \
typing/typedtree.cmi typing/subst.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/datarepr.cmi \
- typing/ctype.cmi typing/btype.cmi parsing/asttypes.cmi \
- parsing/ast_helper.cmi typing/parmatch.cmi
+ parsing/location.cmi typing/ident.cmi typing/env.cmi typing/ctype.cmi \
+ typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \
+ typing/parmatch.cmi
typing/parmatch.cmx : utils/warnings.cmx typing/types.cmx \
typing/typedtree.cmx typing/subst.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/datarepr.cmx \
- typing/ctype.cmx typing/btype.cmx parsing/asttypes.cmi \
- parsing/ast_helper.cmx typing/parmatch.cmi
+ parsing/location.cmx typing/ident.cmx typing/env.cmx typing/ctype.cmx \
+ typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \
+ typing/parmatch.cmi
typing/path.cmo : typing/ident.cmi typing/path.cmi
typing/path.cmx : typing/ident.cmx typing/path.cmi
typing/predef.cmo : typing/types.cmi typing/path.cmi parsing/location.cmi \
@@ -278,8 +282,8 @@ typing/subst.cmx : typing/types.cmx utils/tbl.cmx typing/path.cmx \
typing/btype.cmx parsing/ast_mapper.cmx typing/subst.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 \
+ typing/typecore.cmi parsing/syntaxerr.cmi typing/subst.cmi \
+ typing/stypes.cmi typing/printtyp.cmi typing/predef.cmi typing/path.cmi \
parsing/parsetree.cmi typing/parmatch.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 \
@@ -287,43 +291,43 @@ typing/typeclass.cmo : utils/warnings.cmi typing/typetexp.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 \
+ typing/typecore.cmx parsing/syntaxerr.cmx typing/subst.cmx \
+ typing/stypes.cmx typing/printtyp.cmx typing/predef.cmx typing/path.cmx \
parsing/parsetree.cmi typing/parmatch.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 typing/btype.cmx parsing/asttypes.cmi \
parsing/ast_helper.cmx typing/typeclass.cmi
typing/typecore.cmo : utils/warnings.cmi typing/typetexp.cmi \
- typing/types.cmi typing/typedtree.cmi typing/subst.cmi typing/stypes.cmi \
- typing/printtyp.cmi typing/primitive.cmi typing/predef.cmi \
- typing/path.cmi parsing/parsetree.cmi typing/parmatch.cmi \
- typing/oprint.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 typing/btype.cmi \
- parsing/asttypes.cmi parsing/ast_helper.cmi typing/annot.cmi \
- typing/typecore.cmi
+ typing/types.cmi typing/typedtree.cmi parsing/syntaxerr.cmi \
+ typing/subst.cmi typing/stypes.cmi typing/printtyp.cmi \
+ typing/primitive.cmi typing/predef.cmi typing/path.cmi \
+ parsing/parsetree.cmi typing/parmatch.cmi typing/oprint.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 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/typedtree.cmx typing/subst.cmx typing/stypes.cmx \
- typing/printtyp.cmx typing/primitive.cmx typing/predef.cmx \
- typing/path.cmx parsing/parsetree.cmi typing/parmatch.cmx \
- typing/oprint.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 typing/btype.cmx \
- parsing/asttypes.cmi parsing/ast_helper.cmx typing/annot.cmi \
- typing/typecore.cmi
+ typing/types.cmx typing/typedtree.cmx parsing/syntaxerr.cmx \
+ typing/subst.cmx typing/stypes.cmx typing/printtyp.cmx \
+ typing/primitive.cmx typing/predef.cmx typing/path.cmx \
+ parsing/parsetree.cmi typing/parmatch.cmx typing/oprint.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 typing/btype.cmx parsing/asttypes.cmi \
+ parsing/ast_helper.cmx typing/annot.cmi typing/typecore.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 \
+ typing/types.cmi typing/typedtree.cmi parsing/syntaxerr.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/ctype.cmi utils/config.cmi \
utils/clflags.cmi typing/btype.cmi parsing/asttypes.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 \
+ typing/types.cmx typing/typedtree.cmx parsing/syntaxerr.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/ctype.cmx utils/config.cmx \
utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \
@@ -351,8 +355,8 @@ typing/typemod.cmo : utils/warnings.cmi typing/typetexp.cmi typing/types.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 \
- utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi typing/annot.cmi \
- typing/typemod.cmi
+ utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \
+ parsing/ast_mapper.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 \
@@ -360,8 +364,8 @@ typing/typemod.cmx : utils/warnings.cmx typing/typetexp.cmx typing/types.cmx \
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 \
- utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi typing/annot.cmi \
- typing/typemod.cmi
+ utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \
+ parsing/ast_mapper.cmx typing/annot.cmi typing/typemod.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
@@ -369,21 +373,21 @@ 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/typetexp.cmo : utils/warnings.cmi typing/types.cmi \
- typing/typedtree.cmi utils/tbl.cmi typing/printtyp.cmi typing/path.cmi \
- parsing/parsetree.cmi utils/misc.cmi parsing/longident.cmi \
- parsing/location.cmi typing/env.cmi typing/ctype.cmi utils/clflags.cmi \
- typing/btype.cmi parsing/asttypes.cmi parsing/ast_helper.cmi \
- typing/typetexp.cmi
+ typing/typedtree.cmi utils/tbl.cmi parsing/syntaxerr.cmi \
+ typing/printtyp.cmi typing/path.cmi parsing/parsetree.cmi utils/misc.cmi \
+ parsing/longident.cmi parsing/location.cmi typing/env.cmi \
+ typing/ctype.cmi utils/clflags.cmi typing/btype.cmi parsing/asttypes.cmi \
+ parsing/ast_mapper.cmi parsing/ast_helper.cmi typing/typetexp.cmi
typing/typetexp.cmx : utils/warnings.cmx typing/types.cmx \
- typing/typedtree.cmx utils/tbl.cmx typing/printtyp.cmx typing/path.cmx \
- parsing/parsetree.cmi utils/misc.cmx parsing/longident.cmx \
- parsing/location.cmx typing/env.cmx typing/ctype.cmx utils/clflags.cmx \
- typing/btype.cmx parsing/asttypes.cmi parsing/ast_helper.cmx \
- typing/typetexp.cmi
+ typing/typedtree.cmx utils/tbl.cmx parsing/syntaxerr.cmx \
+ typing/printtyp.cmx typing/path.cmx parsing/parsetree.cmi utils/misc.cmx \
+ parsing/longident.cmx parsing/location.cmx typing/env.cmx \
+ typing/ctype.cmx utils/clflags.cmx typing/btype.cmx parsing/asttypes.cmi \
+ parsing/ast_mapper.cmx parsing/ast_helper.cmx typing/typetexp.cmi
bytecomp/bytegen.cmi : bytecomp/lambda.cmi bytecomp/instruct.cmi
bytecomp/bytelibrarian.cmi :
bytecomp/bytelink.cmi : bytecomp/symtable.cmi bytecomp/cmo_format.cmi
-bytecomp/bytepackager.cmi : typing/ident.cmi
+bytecomp/bytepackager.cmi : typing/ident.cmi typing/env.cmi
bytecomp/bytesections.cmi :
bytecomp/cmo_format.cmi : bytecomp/lambda.cmi typing/ident.cmi
bytecomp/dll.cmi :
@@ -448,22 +452,20 @@ bytecomp/bytepackager.cmx : typing/typemod.cmx bytecomp/translmod.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/bytesections.cmo : utils/misc.cmi utils/config.cmi \
- bytecomp/bytesections.cmi
-bytecomp/bytesections.cmx : utils/misc.cmx utils/config.cmx \
- bytecomp/bytesections.cmi
+bytecomp/bytesections.cmo : utils/config.cmi bytecomp/bytesections.cmi
+bytecomp/bytesections.cmx : utils/config.cmx bytecomp/bytesections.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/emitcode.cmo : bytecomp/translmod.cmi typing/primitive.cmi \
- bytecomp/opcodes.cmo utils/misc.cmi bytecomp/meta.cmi bytecomp/lambda.cmi \
- bytecomp/instruct.cmi typing/env.cmi utils/config.cmi \
- bytecomp/cmo_format.cmi utils/clflags.cmi typing/btype.cmi \
- parsing/asttypes.cmi bytecomp/emitcode.cmi
+ bytecomp/opcodes.cmo utils/misc.cmi bytecomp/meta.cmi \
+ parsing/location.cmi bytecomp/lambda.cmi bytecomp/instruct.cmi \
+ typing/env.cmi utils/config.cmi bytecomp/cmo_format.cmi utils/clflags.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 bytecomp/lambda.cmx \
- bytecomp/instruct.cmx typing/env.cmx utils/config.cmx \
- bytecomp/cmo_format.cmi utils/clflags.cmx typing/btype.cmx \
- parsing/asttypes.cmi bytecomp/emitcode.cmi
+ bytecomp/opcodes.cmx utils/misc.cmx bytecomp/meta.cmx \
+ parsing/location.cmx bytecomp/lambda.cmx bytecomp/instruct.cmx \
+ typing/env.cmx utils/config.cmx bytecomp/cmo_format.cmi utils/clflags.cmx \
+ typing/btype.cmx parsing/asttypes.cmi bytecomp/emitcode.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
@@ -508,12 +510,12 @@ bytecomp/printlambda.cmx : typing/types.cmx typing/primitive.cmx \
parsing/asttypes.cmi bytecomp/printlambda.cmi
bytecomp/runtimedef.cmo : bytecomp/runtimedef.cmi
bytecomp/runtimedef.cmx : bytecomp/runtimedef.cmi
-bytecomp/simplif.cmo : utils/tbl.cmi typing/stypes.cmi bytecomp/lambda.cmi \
- typing/ident.cmi utils/clflags.cmi parsing/asttypes.cmi typing/annot.cmi \
- bytecomp/simplif.cmi
-bytecomp/simplif.cmx : utils/tbl.cmx typing/stypes.cmx bytecomp/lambda.cmx \
- typing/ident.cmx utils/clflags.cmx parsing/asttypes.cmi typing/annot.cmi \
- bytecomp/simplif.cmi
+bytecomp/simplif.cmo : utils/tbl.cmi typing/stypes.cmi utils/misc.cmi \
+ bytecomp/lambda.cmi typing/ident.cmi utils/clflags.cmi \
+ parsing/asttypes.cmi typing/annot.cmi bytecomp/simplif.cmi
+bytecomp/simplif.cmx : utils/tbl.cmx typing/stypes.cmx utils/misc.cmx \
+ bytecomp/lambda.cmx typing/ident.cmx utils/clflags.cmx \
+ parsing/asttypes.cmi typing/annot.cmi bytecomp/simplif.cmi
bytecomp/switch.cmo : bytecomp/switch.cmi
bytecomp/switch.cmx : bytecomp/switch.cmi
bytecomp/symtable.cmo : utils/tbl.cmi bytecomp/runtimedef.cmi \
@@ -576,10 +578,11 @@ bytecomp/typeopt.cmo : typing/types.cmi typing/typedtree.cmi \
bytecomp/typeopt.cmx : typing/types.cmx typing/typedtree.cmx \
typing/predef.cmx typing/path.cmx bytecomp/lambda.cmx typing/ident.cmx \
typing/env.cmx typing/ctype.cmx bytecomp/typeopt.cmi
+asmcomp/CSEgen.cmi : asmcomp/mach.cmi
asmcomp/asmgen.cmi : bytecomp/lambda.cmi asmcomp/cmm.cmi
asmcomp/asmlibrarian.cmi :
asmcomp/asmlink.cmi : asmcomp/cmx_format.cmi
-asmcomp/asmpackager.cmi :
+asmcomp/asmpackager.cmi : typing/env.cmi
asmcomp/clambda.cmi : bytecomp/lambda.cmi typing/ident.cmi \
asmcomp/debuginfo.cmi parsing/asttypes.cmi
asmcomp/closure.cmi : bytecomp/lambda.cmi asmcomp/clambda.cmi
@@ -592,6 +595,7 @@ asmcomp/coloring.cmi :
asmcomp/comballoc.cmi : asmcomp/mach.cmi
asmcomp/compilenv.cmi : typing/ident.cmi asmcomp/cmx_format.cmi \
asmcomp/clambda.cmi
+asmcomp/deadcode.cmi : asmcomp/mach.cmi
asmcomp/debuginfo.cmi : parsing/location.cmi bytecomp/lambda.cmi
asmcomp/emit.cmi : asmcomp/linearize.cmi asmcomp/cmm.cmi
asmcomp/emitaux.cmi : asmcomp/debuginfo.cmi
@@ -617,6 +621,10 @@ asmcomp/selection.cmi : asmcomp/mach.cmi asmcomp/cmm.cmi
asmcomp/spill.cmi : asmcomp/mach.cmi
asmcomp/split.cmi : asmcomp/mach.cmi
asmcomp/strmatch.cmi : asmcomp/cmm.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/mach.cmi asmcomp/CSEgen.cmi
+asmcomp/CSEgen.cmx : asmcomp/reg.cmx asmcomp/mach.cmx asmcomp/CSEgen.cmi
asmcomp/arch.cmo :
asmcomp/arch.cmx :
asmcomp/asmgen.cmo : bytecomp/translmod.cmi asmcomp/split.cmi \
@@ -625,20 +633,20 @@ asmcomp/asmgen.cmo : bytecomp/translmod.cmi asmcomp/split.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/linearize.cmi asmcomp/interf.cmi \
- asmcomp/emitaux.cmi asmcomp/emit.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/asmgen.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/CSE.cmo asmcomp/asmgen.cmi
asmcomp/asmgen.cmx : bytecomp/translmod.cmx asmcomp/split.cmx \
asmcomp/spill.cmx asmcomp/selection.cmx asmcomp/scheduling.cmx \
asmcomp/reload.cmx asmcomp/reg.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/linearize.cmx asmcomp/interf.cmx \
- asmcomp/emitaux.cmx asmcomp/emit.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/asmgen.cmi
+ 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/CSE.cmx asmcomp/asmgen.cmi
asmcomp/asmlibrarian.cmo : utils/misc.cmi parsing/location.cmi \
utils/config.cmi asmcomp/compilenv.cmi asmcomp/cmx_format.cmi \
utils/clflags.cmi asmcomp/clambda.cmi utils/ccomp.cmi asmcomp/asmlink.cmi \
@@ -719,6 +727,10 @@ asmcomp/compilenv.cmo : utils/misc.cmi parsing/location.cmi typing/ident.cmi \
asmcomp/compilenv.cmx : utils/misc.cmx parsing/location.cmx typing/ident.cmx \
typing/env.cmx utils/config.cmx asmcomp/cmx_format.cmi \
asmcomp/clambda.cmx asmcomp/compilenv.cmi
+asmcomp/deadcode.cmo : asmcomp/reg.cmi asmcomp/proc.cmi asmcomp/mach.cmi \
+ asmcomp/deadcode.cmi
+asmcomp/deadcode.cmx : asmcomp/reg.cmx asmcomp/proc.cmx asmcomp/mach.cmx \
+ asmcomp/deadcode.cmi
asmcomp/debuginfo.cmo : parsing/location.cmi bytecomp/lambda.cmi \
asmcomp/debuginfo.cmi
asmcomp/debuginfo.cmx : parsing/location.cmx bytecomp/lambda.cmx \
@@ -852,7 +864,8 @@ driver/compile.cmo : utils/warnings.cmi typing/typemod.cmi \
parsing/printast.cmi parsing/pprintast.cmi driver/pparse.cmi \
utils/misc.cmi parsing/location.cmi typing/includemod.cmi typing/env.cmi \
bytecomp/emitcode.cmi driver/compmisc.cmi driver/compenv.cmi \
- utils/clflags.cmi utils/ccomp.cmi bytecomp/bytegen.cmi driver/compile.cmi
+ utils/clflags.cmi utils/ccomp.cmi bytecomp/bytegen.cmi \
+ parsing/ast_mapper.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 typing/printtyped.cmx \
@@ -860,11 +873,16 @@ driver/compile.cmx : utils/warnings.cmx typing/typemod.cmx \
parsing/printast.cmx parsing/pprintast.cmx driver/pparse.cmx \
utils/misc.cmx parsing/location.cmx typing/includemod.cmx typing/env.cmx \
bytecomp/emitcode.cmx driver/compmisc.cmx driver/compenv.cmx \
- utils/clflags.cmx utils/ccomp.cmx bytecomp/bytegen.cmx driver/compile.cmi
-driver/compmisc.cmo : utils/misc.cmi typing/ident.cmi typing/env.cmi \
- utils/config.cmi driver/compenv.cmi utils/clflags.cmi driver/compmisc.cmi
-driver/compmisc.cmx : utils/misc.cmx typing/ident.cmx typing/env.cmx \
- utils/config.cmx driver/compenv.cmx utils/clflags.cmx driver/compmisc.cmi
+ utils/clflags.cmx utils/ccomp.cmx bytecomp/bytegen.cmx \
+ parsing/ast_mapper.cmx driver/compile.cmi
+driver/compmisc.cmo : typing/typemod.cmi utils/misc.cmi \
+ parsing/longident.cmi parsing/location.cmi typing/ident.cmi \
+ typing/env.cmi utils/config.cmi driver/compenv.cmi utils/clflags.cmi \
+ parsing/asttypes.cmi driver/compmisc.cmi
+driver/compmisc.cmx : typing/typemod.cmx utils/misc.cmx \
+ parsing/longident.cmx parsing/location.cmx typing/ident.cmx \
+ typing/env.cmx utils/config.cmx driver/compenv.cmx utils/clflags.cmx \
+ parsing/asttypes.cmi driver/compmisc.cmi
driver/errors.cmo : parsing/location.cmi driver/errors.cmi
driver/errors.cmx : parsing/location.cmx driver/errors.cmi
driver/main.cmo : utils/warnings.cmi utils/misc.cmi driver/main_args.cmi \
@@ -886,7 +904,8 @@ driver/optcompile.cmo : utils/warnings.cmi typing/typemod.cmi \
parsing/pprintast.cmi driver/pparse.cmi utils/misc.cmi \
typing/includemod.cmi typing/env.cmi utils/config.cmi driver/compmisc.cmi \
asmcomp/compilenv.cmi driver/compenv.cmi utils/clflags.cmi \
- utils/ccomp.cmi asmcomp/asmgen.cmi driver/optcompile.cmi
+ utils/ccomp.cmi parsing/ast_mapper.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 typing/printtyped.cmx \
@@ -894,7 +913,8 @@ driver/optcompile.cmx : utils/warnings.cmx typing/typemod.cmx \
parsing/pprintast.cmx driver/pparse.cmx utils/misc.cmx \
typing/includemod.cmx typing/env.cmx utils/config.cmx driver/compmisc.cmx \
asmcomp/compilenv.cmx driver/compenv.cmx utils/clflags.cmx \
- utils/ccomp.cmx asmcomp/asmgen.cmx driver/optcompile.cmi
+ utils/ccomp.cmx parsing/ast_mapper.cmx asmcomp/asmgen.cmx \
+ driver/optcompile.cmi
driver/opterrors.cmo : parsing/location.cmi driver/opterrors.cmi
driver/opterrors.cmx : parsing/location.cmx driver/opterrors.cmi
driver/optmain.cmo : utils/warnings.cmi asmcomp/printmach.cmi \
@@ -909,10 +929,14 @@ driver/optmain.cmx : utils/warnings.cmx asmcomp/printmach.cmx \
driver/compenv.cmx utils/clflags.cmx asmcomp/asmpackager.cmx \
asmcomp/asmlink.cmx asmcomp/asmlibrarian.cmx asmcomp/arch.cmx \
driver/optmain.cmi
-driver/pparse.cmo : parsing/parse.cmi utils/misc.cmi parsing/location.cmi \
- utils/config.cmi utils/clflags.cmi utils/ccomp.cmi driver/pparse.cmi
-driver/pparse.cmx : parsing/parse.cmx utils/misc.cmx parsing/location.cmx \
- utils/config.cmx utils/clflags.cmx utils/ccomp.cmx driver/pparse.cmi
+driver/pparse.cmo : parsing/parsetree.cmi parsing/parse.cmi utils/misc.cmi \
+ parsing/longident.cmi parsing/location.cmi utils/config.cmi \
+ utils/clflags.cmi utils/ccomp.cmi parsing/asttypes.cmi \
+ parsing/ast_mapper.cmi parsing/ast_helper.cmi driver/pparse.cmi
+driver/pparse.cmx : parsing/parsetree.cmi parsing/parse.cmx utils/misc.cmx \
+ parsing/longident.cmx parsing/location.cmx utils/config.cmx \
+ utils/clflags.cmx utils/ccomp.cmx parsing/asttypes.cmi \
+ parsing/ast_mapper.cmx parsing/ast_helper.cmx driver/pparse.cmi
toplevel/genprintval.cmi : typing/types.cmi typing/path.cmi \
typing/outcometree.cmi typing/env.cmi
toplevel/opttopdirs.cmi : parsing/longident.cmi
@@ -976,25 +1000,31 @@ toplevel/opttoploop.cmx : utils/warnings.cmx typing/types.cmx \
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/compenv.cmi utils/clflags.cmi toplevel/opttopmain.cmi
+ driver/compenv.cmi utils/clflags.cmi parsing/ast_mapper.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/compenv.cmx utils/clflags.cmx toplevel/opttopmain.cmi
+ driver/compenv.cmx utils/clflags.cmx parsing/ast_mapper.cmx \
+ toplevel/opttopmain.cmi
toplevel/opttopstart.cmo : toplevel/opttopmain.cmi
toplevel/opttopstart.cmx : toplevel/opttopmain.cmx
-toplevel/topdirs.cmo : utils/warnings.cmi typing/types.cmi \
- toplevel/trace.cmi toplevel/toploop.cmi bytecomp/symtable.cmi \
- typing/printtyp.cmi typing/path.cmi bytecomp/opcodes.cmo utils/misc.cmi \
- bytecomp/meta.cmi parsing/longident.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 toplevel/topdirs.cmi
-toplevel/topdirs.cmx : utils/warnings.cmx typing/types.cmx \
- toplevel/trace.cmx toplevel/toploop.cmx bytecomp/symtable.cmx \
- typing/printtyp.cmx typing/path.cmx bytecomp/opcodes.cmx utils/misc.cmx \
- bytecomp/meta.cmx parsing/longident.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 toplevel/topdirs.cmi
+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 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 \
+ parsing/asttypes.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 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 \
+ parsing/asttypes.cmi toplevel/topdirs.cmi
toplevel/toploop.cmo : utils/warnings.cmi typing/types.cmi \
typing/typemod.cmi typing/typedtree.cmi typing/typecore.cmi \
bytecomp/translmod.cmi bytecomp/symtable.cmi bytecomp/simplif.cmi \
@@ -1026,11 +1056,11 @@ toplevel/toploop.cmx : utils/warnings.cmx typing/types.cmx \
toplevel/topmain.cmo : utils/warnings.cmi toplevel/toploop.cmi \
toplevel/topdirs.cmi utils/misc.cmi driver/main_args.cmi \
parsing/location.cmi utils/config.cmi driver/compenv.cmi \
- utils/clflags.cmi toplevel/topmain.cmi
+ utils/clflags.cmi parsing/ast_mapper.cmi toplevel/topmain.cmi
toplevel/topmain.cmx : utils/warnings.cmx toplevel/toploop.cmx \
toplevel/topdirs.cmx utils/misc.cmx driver/main_args.cmx \
parsing/location.cmx utils/config.cmx driver/compenv.cmx \
- utils/clflags.cmx toplevel/topmain.cmi
+ utils/clflags.cmx parsing/ast_mapper.cmx toplevel/topmain.cmi
toplevel/topstart.cmo : toplevel/topmain.cmi
toplevel/topstart.cmx : toplevel/topmain.cmx
toplevel/trace.cmo : typing/types.cmi toplevel/toploop.cmi \
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000000..2817041cf7
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,2590 @@
+# This file has been automatically generated using `git svn show-ignore > .gitignore`
+# from trunk@14716 (Thu May 1 09:28:35 2014).
+# Do not hesitate to refresh it from time to time.
+
+# /
+/*.o
+/*.a
+/*.so
+/*.obj
+/*.lib
+/*.dll
+/*.cm[ioxat]
+/*.cmx[as]
+/*.cmti
+/*.annot
+/*.result
+/*.byte
+/*.native
+/program
+/*.exe
+/*.exe.manifest
+/.depend
+/.depend.nt
+/.DS_Store
+/configure
+/ocamlc
+/ocamlc.opt
+/expunge
+/ocaml
+/ocamlopt
+/ocamlopt.opt
+/ocamlcomp.sh
+/ocamlcompopt.sh
+/package-macosx
+/ocamlnat
+
+# /asmcomp/
+/asmcomp/*.o
+/asmcomp/*.a
+/asmcomp/*.so
+/asmcomp/*.obj
+/asmcomp/*.lib
+/asmcomp/*.dll
+/asmcomp/*.cm[ioxat]
+/asmcomp/*.cmx[as]
+/asmcomp/*.cmti
+/asmcomp/*.annot
+/asmcomp/*.result
+/asmcomp/*.byte
+/asmcomp/*.native
+/asmcomp/program
+/asmcomp/*.exe
+/asmcomp/*.exe.manifest
+/asmcomp/.depend
+/asmcomp/.depend.nt
+/asmcomp/.DS_Store
+/asmcomp/emit.ml
+/asmcomp/arch.ml
+/asmcomp/proc.ml
+/asmcomp/selection.ml
+/asmcomp/reload.ml
+/asmcomp/scheduling.ml
+/asmcomp/CSE.ml
+
+# /asmcomp/amd64/
+/asmcomp/amd64/*.o
+/asmcomp/amd64/*.a
+/asmcomp/amd64/*.so
+/asmcomp/amd64/*.obj
+/asmcomp/amd64/*.cm[ioxat]
+/asmcomp/amd64/*.cmx[as]
+/asmcomp/amd64/*.cmti
+/asmcomp/amd64/*.annot
+/asmcomp/amd64/*.result
+/asmcomp/amd64/*.byte
+/asmcomp/amd64/*.native
+/asmcomp/amd64/program
+/asmcomp/amd64/program.exe
+/asmcomp/amd64/.depend
+/asmcomp/amd64/.depend.nt
+/asmcomp/amd64/.DS_Store
+
+# /asmrun/
+/asmrun/*.o
+/asmrun/*.a
+/asmrun/*.so
+/asmrun/*.obj
+/asmrun/*.lib
+/asmrun/*.dll
+/asmrun/*.cm[ioxat]
+/asmrun/*.cmx[as]
+/asmrun/*.cmti
+/asmrun/*.annot
+/asmrun/*.result
+/asmrun/*.byte
+/asmrun/*.native
+/asmrun/program
+/asmrun/*.exe
+/asmrun/.depend
+/asmrun/.depend.nt
+/asmrun/.DS_Store
+/asmrun/*.p.c
+/asmrun/*.d.c
+/asmrun/libasmrun.a
+/asmrun/libasmrunp.a
+/asmrun/main.c
+/asmrun/misc.c
+/asmrun/freelist.c
+/asmrun/major_gc.c
+/asmrun/minor_gc.c
+/asmrun/memory.c
+/asmrun/alloc.c
+/asmrun/array.c
+/asmrun/compare.c
+/asmrun/ints.c
+/asmrun/floats.c
+/asmrun/str.c
+/asmrun/io.c
+/asmrun/extern.c
+/asmrun/intern.c
+/asmrun/hash.c
+/asmrun/sys.c
+/asmrun/parsing.c
+/asmrun/gc_ctrl.c
+/asmrun/terminfo.c
+/asmrun/md5.c
+/asmrun/obj.c
+/asmrun/lexing.c
+/asmrun/printexc.c
+/asmrun/callback.c
+/asmrun/weak.c
+/asmrun/compact.c
+/asmrun/finalise.c
+/asmrun/custom.c
+/asmrun/meta.c
+/asmrun/globroots.c
+/asmrun/unix.c
+/asmrun/dynlink.c
+/asmrun/signals.c
+/asmrun/debugger.c
+/asmrun/.depend.nt
+
+# /boot/
+/boot/*.o
+/boot/*.a
+/boot/*.so
+/boot/*.obj
+/boot/*.lib
+/boot/*.dll
+/boot/*.cm[ioxat]
+/boot/*.cmx[as]
+/boot/*.cmti
+/boot/*.annot
+/boot/*.result
+/boot/*.byte
+/boot/*.native
+/boot/program
+/boot/*.exe
+/boot/*.exe.manifest
+/boot/.depend
+/boot/.depend.nt
+/boot/.DS_Store
+/boot/Saved
+/boot/ocamlrun
+/boot/ocamlrun.exe
+/boot/ocamlyacc
+/boot/ocamlyacc.exe
+/boot/camlheader
+
+# /bytecomp/
+/bytecomp/*.o
+/bytecomp/*.a
+/bytecomp/*.so
+/bytecomp/*.obj
+/bytecomp/*.lib
+/bytecomp/*.dll
+/bytecomp/*.cm[ioxat]
+/bytecomp/*.cmx[as]
+/bytecomp/*.cmti
+/bytecomp/*.annot
+/bytecomp/*.result
+/bytecomp/*.byte
+/bytecomp/*.native
+/bytecomp/program
+/bytecomp/*.exe
+/bytecomp/.depend
+/bytecomp/.depend.nt
+/bytecomp/.DS_Store
+/bytecomp/runtimedef.ml
+/bytecomp/opcodes.ml
+
+# /byterun/
+/byterun/*.o
+/byterun/*.a
+/byterun/*.so
+/byterun/*.obj
+/byterun/*.cm[ioxa]
+/byterun/*.cmx[as]
+/byterun/*.annot
+/byterun/*.result
+/byterun/*.byte
+/byterun/*.native
+/byterun/program
+/byterun/program.exe
+/byterun/.depend
+/byterun/.depend.nt
+/byterun/.DS_Store
+/byterun/jumptbl.h
+/byterun/primitives
+/byterun/prims.c
+/byterun/opnames.h
+/byterun/version.h
+/byterun/ocamlrun
+/byterun/ocamlrun.exe
+/byterun/ocamlrund
+/byterun/ocamlrund.exe
+/byterun/ld.conf
+/byterun/interp.a.lst
+/byterun/*.[sd]obj
+/byterun/*.lib
+/byterun/.gdb_history
+/byterun/*.d.c
+/byterun/*.pic.c
+
+# /compilerlibs/
+/compilerlibs/*
+
+# /config/
+/config/*.o
+/config/*.a
+/config/*.so
+/config/*.obj
+/config/*.lib
+/config/*.dll
+/config/*.cm[ioxat]
+/config/*.cmx[as]
+/config/*.cmti
+/config/*.annot
+/config/*.result
+/config/*.byte
+/config/*.native
+/config/program
+/config/*.exe
+/config/*.exe.manifest
+/config/.depend
+/config/.depend.nt
+/config/.DS_Store
+/config/m.h
+/config/s.h
+/config/Makefile
+
+# /config/auto-aux/
+/config/auto-aux/*.o
+/config/auto-aux/*.a
+/config/auto-aux/*.so
+/config/auto-aux/*.obj
+/config/auto-aux/*.cm[ioxa]
+/config/auto-aux/*.cmx[as]
+/config/auto-aux/*.annot
+/config/auto-aux/*.result
+/config/auto-aux/*.byte
+/config/auto-aux/*.native
+/config/auto-aux/program
+/config/auto-aux/.depend
+/config/auto-aux/.depend.nt
+/config/auto-aux/.DS_Store
+/config/auto-aux/camlp4_config.ml
+
+# /config/gnu/
+
+# /debugger/
+/debugger/*.o
+/debugger/*.a
+/debugger/*.so
+/debugger/*.obj
+/debugger/*.cm[ioxa]
+/debugger/*.cmx[as]
+/debugger/*.annot
+/debugger/*.result
+/debugger/*.byte
+/debugger/*.native
+/debugger/program
+/debugger/program.exe
+/debugger/.depend
+/debugger/.depend.nt
+/debugger/.DS_Store
+/debugger/lexer.ml
+/debugger/parser.ml
+/debugger/parser.mli
+/debugger/ocamldebug
+/debugger/ocamldebug.exe
+/debugger/dynlink.ml
+/debugger/dynlink.mli
+
+# /driver/
+/driver/*.o
+/driver/*.a
+/driver/*.so
+/driver/*.obj
+/driver/*.lib
+/driver/*.dll
+/driver/*.cm[ioxat]
+/driver/*.cmx[as]
+/driver/*.cmti
+/driver/*.annot
+/driver/*.result
+/driver/*.byte
+/driver/*.native
+/driver/program
+/driver/*.exe
+/driver/*.exe.manifest
+/driver/.depend
+/driver/.depend.nt
+/driver/.DS_Store
+
+# /emacs/
+/emacs/*.o
+/emacs/*.a
+/emacs/*.so
+/emacs/*.obj
+/emacs/*.lib
+/emacs/*.dll
+/emacs/*.cm[ioxat]
+/emacs/*.cmx[as]
+/emacs/*.cmti
+/emacs/*.annot
+/emacs/*.result
+/emacs/*.byte
+/emacs/*.native
+/emacs/program
+/emacs/*.exe
+/emacs/*.exe.manifest
+/emacs/.depend
+/emacs/.depend.nt
+/emacs/.DS_Store
+/emacs/ocamltags
+/emacs/*.elc
+
+# /experimental/
+
+# /experimental/garrigue/
+/experimental/garrigue/*.out
+/experimental/garrigue/*.out2
+
+# /lex/
+/lex/*.o
+/lex/*.a
+/lex/*.so
+/lex/*.obj
+/lex/*.lib
+/lex/*.dll
+/lex/*.cm[ioxat]
+/lex/*.cmx[as]
+/lex/*.cmti
+/lex/*.annot
+/lex/*.result
+/lex/*.byte
+/lex/*.native
+/lex/program
+/lex/*.exe
+/lex/*.exe.manifest
+/lex/.depend
+/lex/.depend.nt
+/lex/.DS_Store
+/lex/parser.ml
+/lex/parser.mli
+/lex/lexer.ml
+/lex/ocamllex
+/lex/ocamllex.opt
+/lex/parser.output
+
+# /ocamlbuild/
+/ocamlbuild/*.o
+/ocamlbuild/*.a
+/ocamlbuild/*.so
+/ocamlbuild/*.obj
+/ocamlbuild/*.lib
+/ocamlbuild/*.dll
+/ocamlbuild/*.cm[ioxat]
+/ocamlbuild/*.cmx[as]
+/ocamlbuild/*.cmti
+/ocamlbuild/*.annot
+/ocamlbuild/*.byte
+/ocamlbuild/*.native
+/ocamlbuild/ocamlbuild_config.ml
+/ocamlbuild/lexers.ml
+/ocamlbuild/glob_lexer.ml
+
+# /ocamldoc/
+/ocamldoc/*.o
+/ocamldoc/*.a
+/ocamldoc/*.so
+/ocamldoc/*.obj
+/ocamldoc/*.lib
+/ocamldoc/*.dll
+/ocamldoc/*.cm[ioxat]
+/ocamldoc/*.cmx[as]
+/ocamldoc/*.cmti
+/ocamldoc/*.annot
+/ocamldoc/*.result
+/ocamldoc/*.byte
+/ocamldoc/*.native
+/ocamldoc/program
+/ocamldoc/*.exe
+/ocamldoc/.depend
+/ocamldoc/.depend.nt
+/ocamldoc/.DS_Store
+/ocamldoc/ocamldoc
+/ocamldoc/ocamldoc.opt
+/ocamldoc/odoc_crc.ml
+/ocamldoc/odoc_lexer.ml
+/ocamldoc/odoc_ocamlhtml.ml
+/ocamldoc/odoc_parser.ml
+/ocamldoc/odoc_parser.mli
+/ocamldoc/odoc_see_lexer.ml
+/ocamldoc/odoc_text_lexer.ml
+/ocamldoc/odoc_text_parser.ml
+/ocamldoc/odoc_text_parser.mli
+/ocamldoc/stdlib_man
+/ocamldoc/*.output
+/ocamldoc/test_stdlib
+/ocamldoc/test_latex
+/ocamldoc/test
+
+# /ocamldoc/generators/
+/ocamldoc/generators/*.o
+/ocamldoc/generators/*.a
+/ocamldoc/generators/*.so
+/ocamldoc/generators/*.obj
+/ocamldoc/generators/*.lib
+/ocamldoc/generators/*.dll
+/ocamldoc/generators/*.cm[ioxat]
+/ocamldoc/generators/*.cmx[as]
+/ocamldoc/generators/*.cmti
+/ocamldoc/generators/*.annot
+/ocamldoc/generators/*.result
+/ocamldoc/generators/*.byte
+/ocamldoc/generators/*.native
+/ocamldoc/generators/program
+/ocamldoc/generators/*.exe
+/ocamldoc/generators/*.exe.manifest
+/ocamldoc/generators/.depend
+/ocamldoc/generators/.depend.nt
+/ocamldoc/generators/.DS_Store
+
+# /otherlibs/
+/otherlibs/.depend
+/otherlibs/configure
+/otherlibs/ocamlc
+/otherlibs/ocamlc.opt
+/otherlibs/expunge
+/otherlibs/ocaml
+/otherlibs/ocamlopt
+/otherlibs/ocamlopt.opt
+/otherlibs/ocamlcomp.sh
+/otherlibs/ocamlcompopt.sh
+/otherlibs/package-macosx
+/otherlibs/.DS_Store
+/otherlibs/*.annot
+/otherlibs/_boot_log1
+/otherlibs/_boot_log2
+/otherlibs/_build
+/otherlibs/_log
+/otherlibs/myocamlbuild_config.ml
+/otherlibs/ocamlnat
+/otherlibs/*.cm*
+/otherlibs/*.o
+
+# /otherlibs/bigarray/
+/otherlibs/bigarray/*.o
+/otherlibs/bigarray/*.a
+/otherlibs/bigarray/*.so
+/otherlibs/bigarray/*.obj
+/otherlibs/bigarray/*.lib
+/otherlibs/bigarray/*.dll
+/otherlibs/bigarray/*.cm[ioxat]
+/otherlibs/bigarray/*.cmx[as]
+/otherlibs/bigarray/*.cmti
+/otherlibs/bigarray/*.annot
+/otherlibs/bigarray/*.result
+/otherlibs/bigarray/*.byte
+/otherlibs/bigarray/*.native
+/otherlibs/bigarray/program
+/otherlibs/bigarray/*.exe
+/otherlibs/bigarray/.depend
+/otherlibs/bigarray/.depend.nt
+/otherlibs/bigarray/.DS_Store
+
+# /otherlibs/dynlink/
+/otherlibs/dynlink/*.o
+/otherlibs/dynlink/*.a
+/otherlibs/dynlink/*.so
+/otherlibs/dynlink/*.obj
+/otherlibs/dynlink/*.lib
+/otherlibs/dynlink/*.dll
+/otherlibs/dynlink/*.cm[ioxat]
+/otherlibs/dynlink/*.cmx[as]
+/otherlibs/dynlink/*.cmti
+/otherlibs/dynlink/*.annot
+/otherlibs/dynlink/*.result
+/otherlibs/dynlink/*.byte
+/otherlibs/dynlink/*.native
+/otherlibs/dynlink/program
+/otherlibs/dynlink/*.exe
+/otherlibs/dynlink/.depend
+/otherlibs/dynlink/.depend.nt
+/otherlibs/dynlink/.DS_Store
+/otherlibs/dynlink/extract_crc
+
+# /otherlibs/graph/
+/otherlibs/graph/*.o
+/otherlibs/graph/*.a
+/otherlibs/graph/*.so
+/otherlibs/graph/*.obj
+/otherlibs/graph/*.lib
+/otherlibs/graph/*.dll
+/otherlibs/graph/*.cm[ioxat]
+/otherlibs/graph/*.cmx[as]
+/otherlibs/graph/*.cmti
+/otherlibs/graph/*.annot
+/otherlibs/graph/*.result
+/otherlibs/graph/*.byte
+/otherlibs/graph/*.native
+/otherlibs/graph/program
+/otherlibs/graph/*.exe
+/otherlibs/graph/*.exe.manifest
+/otherlibs/graph/.depend
+/otherlibs/graph/.depend.nt
+/otherlibs/graph/.DS_Store
+
+# /otherlibs/num/
+/otherlibs/num/*.o
+/otherlibs/num/*.a
+/otherlibs/num/*.so
+/otherlibs/num/*.obj
+/otherlibs/num/*.lib
+/otherlibs/num/*.dll
+/otherlibs/num/*.cm[ioxat]
+/otherlibs/num/*.cmx[as]
+/otherlibs/num/*.cmti
+/otherlibs/num/*.annot
+/otherlibs/num/*.result
+/otherlibs/num/*.byte
+/otherlibs/num/*.native
+/otherlibs/num/program
+/otherlibs/num/*.exe
+/otherlibs/num/.depend
+/otherlibs/num/.depend.nt
+/otherlibs/num/.DS_Store
+
+# /otherlibs/str/
+/otherlibs/str/*.o
+/otherlibs/str/*.a
+/otherlibs/str/*.so
+/otherlibs/str/*.obj
+/otherlibs/str/*.lib
+/otherlibs/str/*.dll
+/otherlibs/str/*.cm[ioxat]
+/otherlibs/str/*.cmx[as]
+/otherlibs/str/*.cmti
+/otherlibs/str/*.annot
+/otherlibs/str/*.result
+/otherlibs/str/*.byte
+/otherlibs/str/*.native
+/otherlibs/str/program
+/otherlibs/str/*.exe
+/otherlibs/str/.depend
+/otherlibs/str/.depend.nt
+/otherlibs/str/.DS_Store
+
+# /otherlibs/systhreads/
+/otherlibs/systhreads/*.o
+/otherlibs/systhreads/*.a
+/otherlibs/systhreads/*.so
+/otherlibs/systhreads/*.obj
+/otherlibs/systhreads/*.lib
+/otherlibs/systhreads/*.dll
+/otherlibs/systhreads/*.cm[ioxat]
+/otherlibs/systhreads/*.cmx[as]
+/otherlibs/systhreads/*.cmti
+/otherlibs/systhreads/*.annot
+/otherlibs/systhreads/*.result
+/otherlibs/systhreads/*.byte
+/otherlibs/systhreads/*.native
+/otherlibs/systhreads/program
+/otherlibs/systhreads/*.exe
+/otherlibs/systhreads/.depend
+/otherlibs/systhreads/.depend.nt
+/otherlibs/systhreads/.DS_Store
+/otherlibs/systhreads/thread.ml
+
+# /otherlibs/threads/
+/otherlibs/threads/*.o
+/otherlibs/threads/*.a
+/otherlibs/threads/*.so
+/otherlibs/threads/*.obj
+/otherlibs/threads/*.lib
+/otherlibs/threads/*.dll
+/otherlibs/threads/*.cm[ioxat]
+/otherlibs/threads/*.cmx[as]
+/otherlibs/threads/*.cmti
+/otherlibs/threads/*.annot
+/otherlibs/threads/*.result
+/otherlibs/threads/*.byte
+/otherlibs/threads/*.native
+/otherlibs/threads/program
+/otherlibs/threads/*.exe
+/otherlibs/threads/*.exe.manifest
+/otherlibs/threads/.depend
+/otherlibs/threads/.depend.nt
+/otherlibs/threads/.DS_Store
+/otherlibs/threads/marshal.mli
+/otherlibs/threads/pervasives.mli
+/otherlibs/threads/unix.mli
+
+# /otherlibs/unix/
+/otherlibs/unix/*.o
+/otherlibs/unix/*.a
+/otherlibs/unix/*.so
+/otherlibs/unix/*.obj
+/otherlibs/unix/*.lib
+/otherlibs/unix/*.dll
+/otherlibs/unix/*.cm[ioxat]
+/otherlibs/unix/*.cmx[as]
+/otherlibs/unix/*.cmti
+/otherlibs/unix/*.annot
+/otherlibs/unix/*.result
+/otherlibs/unix/*.byte
+/otherlibs/unix/*.native
+/otherlibs/unix/program
+/otherlibs/unix/*.exe
+/otherlibs/unix/*.exe.manifest
+/otherlibs/unix/.depend
+/otherlibs/unix/.depend.nt
+/otherlibs/unix/.DS_Store
+
+# /otherlibs/win32graph/
+/otherlibs/win32graph/*.o
+/otherlibs/win32graph/*.a
+/otherlibs/win32graph/*.so
+/otherlibs/win32graph/*.obj
+/otherlibs/win32graph/*.lib
+/otherlibs/win32graph/*.dll
+/otherlibs/win32graph/*.cm[ioxat]
+/otherlibs/win32graph/*.cmx[as]
+/otherlibs/win32graph/*.cmti
+/otherlibs/win32graph/*.annot
+/otherlibs/win32graph/*.result
+/otherlibs/win32graph/*.byte
+/otherlibs/win32graph/*.native
+/otherlibs/win32graph/program
+/otherlibs/win32graph/*.exe
+/otherlibs/win32graph/.depend
+/otherlibs/win32graph/.depend.nt
+/otherlibs/win32graph/.DS_Store
+/otherlibs/win32graph/graphics.ml
+/otherlibs/win32graph/graphics.mli
+
+# /otherlibs/win32unix/
+/otherlibs/win32unix/*.o
+/otherlibs/win32unix/*.a
+/otherlibs/win32unix/*.so
+/otherlibs/win32unix/*.obj
+/otherlibs/win32unix/*.lib
+/otherlibs/win32unix/*.dll
+/otherlibs/win32unix/*.cm[ioxat]
+/otherlibs/win32unix/*.cmx[as]
+/otherlibs/win32unix/*.cmti
+/otherlibs/win32unix/*.annot
+/otherlibs/win32unix/*.result
+/otherlibs/win32unix/*.byte
+/otherlibs/win32unix/*.native
+/otherlibs/win32unix/program
+/otherlibs/win32unix/*.exe
+/otherlibs/win32unix/.depend
+/otherlibs/win32unix/.depend.nt
+/otherlibs/win32unix/.DS_Store
+/otherlibs/win32unix/unixLabels.ml*
+/otherlibs/win32unix/unix.mli
+/otherlibs/win32unix/unix.lib
+/otherlibs/win32unix/access.c
+/otherlibs/win32unix/addrofstr.c
+/otherlibs/win32unix/chdir.c
+/otherlibs/win32unix/chmod.c
+/otherlibs/win32unix/cst2constr.c
+/otherlibs/win32unix/cstringv.c
+/otherlibs/win32unix/envir.c
+/otherlibs/win32unix/execv.c
+/otherlibs/win32unix/execve.c
+/otherlibs/win32unix/execvp.c
+/otherlibs/win32unix/exit.c
+/otherlibs/win32unix/getaddrinfo.c
+/otherlibs/win32unix/getcwd.c
+/otherlibs/win32unix/gethost.c
+/otherlibs/win32unix/gethostname.c
+/otherlibs/win32unix/getnameinfo.c
+/otherlibs/win32unix/getproto.c
+/otherlibs/win32unix/getserv.c
+/otherlibs/win32unix/gmtime.c
+/otherlibs/win32unix/putenv.c
+/otherlibs/win32unix/rmdir.c
+/otherlibs/win32unix/socketaddr.c
+/otherlibs/win32unix/strofaddr.c
+/otherlibs/win32unix/time.c
+/otherlibs/win32unix/unlink.c
+/otherlibs/win32unix/utimes.c
+
+# /parsing/
+/parsing/*.o
+/parsing/*.a
+/parsing/*.so
+/parsing/*.obj
+/parsing/*.lib
+/parsing/*.dll
+/parsing/*.cm[ioxat]
+/parsing/*.cmx[as]
+/parsing/*.cmti
+/parsing/*.annot
+/parsing/*.result
+/parsing/*.byte
+/parsing/*.native
+/parsing/program
+/parsing/*.exe
+/parsing/*.exe.manifest
+/parsing/.depend
+/parsing/.depend.nt
+/parsing/.DS_Store
+/parsing/parser.ml
+/parsing/parser.mli
+/parsing/lexer.ml
+/parsing/lexer_tmp.mll
+/parsing/lexer_tmp.ml
+/parsing/linenum.ml
+/parsing/parser.output
+/parsing/parser.automaton
+/parsing/parser.conflicts
+
+# /stdlib/
+/stdlib/*.o
+/stdlib/*.a
+/stdlib/*.so
+/stdlib/*.obj
+/stdlib/*.lib
+/stdlib/*.dll
+/stdlib/*.cm[ioxat]
+/stdlib/*.cmx[as]
+/stdlib/*.cmti
+/stdlib/*.annot
+/stdlib/*.result
+/stdlib/*.byte
+/stdlib/*.native
+/stdlib/program
+/stdlib/*.exe
+/stdlib/.depend
+/stdlib/.depend.nt
+/stdlib/.DS_Store
+/stdlib/camlheader
+/stdlib/camlheaderd
+/stdlib/camlheader_ur
+/stdlib/labelled-*
+/stdlib/caml
+/stdlib/sys.ml
+
+# /testsuite/
+/testsuite/*.o
+/testsuite/*.a
+/testsuite/*.so
+/testsuite/*.obj
+/testsuite/*.cm[ioxa]
+/testsuite/*.cmx[as]
+/testsuite/*.annot
+/testsuite/*.result
+/testsuite/*.byte
+/testsuite/*.native
+/testsuite/program
+/testsuite/.depend
+/testsuite/.depend.nt
+/testsuite/.DS_Store
+/testsuite/_log
+
+# /testsuite/external/
+/testsuite/external/*.o
+/testsuite/external/*.a
+/testsuite/external/*.so
+/testsuite/external/*.obj
+/testsuite/external/*.lib
+/testsuite/external/*.dll
+/testsuite/external/*.cm[ioxat]
+/testsuite/external/*.cmx[as]
+/testsuite/external/*.cmti
+/testsuite/external/*.annot
+/testsuite/external/*.result
+/testsuite/external/*.byte
+/testsuite/external/*.native
+/testsuite/external/program
+/testsuite/external/*.exe
+/testsuite/external/*.exe.manifest
+/testsuite/external/.depend
+/testsuite/external/.depend.nt
+/testsuite/external/.DS_Store
+/testsuite/external/*.tar.gz
+/testsuite/external/*.tar.bz2
+/testsuite/external/*.tgz
+/testsuite/external/*.tbz
+/testsuite/external/*.zip
+/testsuite/external/log-*
+/testsuite/external/log_*
+/testsuite/external/advi
+/testsuite/external/advi-1.10.2
+/testsuite/external/altergo
+/testsuite/external/alt-ergo-0.95.2
+/testsuite/external/binprot
+/testsuite/external/bin_prot-109.30.00
+/testsuite/external/bitstring
+/testsuite/external/ocaml-bitstring-2.0.3
+/testsuite/external/boomerang
+/testsuite/external/boomerang-0.2
+/testsuite/external/calendar
+/testsuite/external/calendar-2.03.2
+/testsuite/external/camlimages
+/testsuite/external/camlimages-4.0.1
+/testsuite/external/camlpdf
+/testsuite/external/camlpdf-0.5
+/testsuite/external/camlp4
+/testsuite/external/camlp4-trunk
+/testsuite/external/camlp5
+/testsuite/external/camlp5-git
+/testsuite/external/camlzip
+/testsuite/external/camlzip-1.04
+/testsuite/external/camomile
+/testsuite/external/camomile-0.8.4
+/testsuite/external/comparelib
+/testsuite/external/comparelib-109.15.00
+/testsuite/external/compcert
+/testsuite/external/compcert-1.13
+/testsuite/external/configfile
+/testsuite/external/config-file-1.1
+/testsuite/external/coq
+/testsuite/external/coq-8.4pl2
+/testsuite/external/core
+/testsuite/external/core-109.37.00
+/testsuite/external/coreextended
+/testsuite/external/core_extended-109.36.00
+/testsuite/external/corekernel
+/testsuite/external/core_kernel-109.37.00
+/testsuite/external/cryptokit
+/testsuite/external/cryptokit-1.6
+/testsuite/external/csv
+/testsuite/external/csv-1.3.1
+/testsuite/external/customprintf
+/testsuite/external/custom_printf-109.27.00
+/testsuite/external/dbm
+/testsuite/external/camldbm-1.0
+/testsuite/external/expect
+/testsuite/external/ocaml-expect-0.0.3
+/testsuite/external/extlib
+/testsuite/external/extlib-1.5.2
+/testsuite/external/fieldslib
+/testsuite/external/fieldslib-109.15.00
+/testsuite/external/fileutils
+/testsuite/external/ocaml-fileutils-0.4.4
+/testsuite/external/findlib
+/testsuite/external/findlib-1.4.1
+/testsuite/external/framac
+/testsuite/external/frama-c-Oxygen-20120901
+/testsuite/external/geneweb
+/testsuite/external/gw-6.05-src
+/testsuite/external/herelib
+/testsuite/external/herelib-109.35.00
+/testsuite/external/hevea
+/testsuite/external/hevea-2.09
+/testsuite/external/kaputt
+/testsuite/external/kaputt-1.2
+/testsuite/external/lablgtk
+/testsuite/external/lablgtk-2.18.0
+/testsuite/external/lablgtkextras
+/testsuite/external/lablgtkextras-1.3
+/testsuite/external/lwt
+/testsuite/external/lwt-2.4.0
+/testsuite/external/menhir
+/testsuite/external/menhir-20120123
+/testsuite/external/mldonkey
+/testsuite/external/mldonkey-3.1.2
+/testsuite/external/mysql
+/testsuite/external/ocaml-mysql-1.0.4
+/testsuite/external/oasis
+/testsuite/external/oasis-0.3.0
+/testsuite/external/obrowser
+/testsuite/external/obrowser-1.1.1
+/testsuite/external/ocamlgraph
+/testsuite/external/ocamlgraph-1.8.2
+/testsuite/external/ocamlify
+/testsuite/external/ocamlify-0.0.1
+/testsuite/external/ocamlmod
+/testsuite/external/ocamlmod-0.0.3
+/testsuite/external/ocamlnet
+/testsuite/external/ocamlnet-3.5.1
+/testsuite/external/ocamlscript
+/testsuite/external/ocamlscript-2.0.3
+/testsuite/external/ocamlssl
+/testsuite/external/ocaml-ssl-0.4.6
+/testsuite/external/ocamltext
+/testsuite/external/ocaml-text-0.5
+/testsuite/external/ocgi
+/testsuite/external/ocgi-0.5
+/testsuite/external/ocsigen
+/testsuite/external/ocsigen-bundle-2.2.2
+/testsuite/external/odn
+/testsuite/external/ocaml-data-notation-0.0.10
+/testsuite/external/omake
+/testsuite/external/omake-0.9.8.6
+/testsuite/external/ounit
+/testsuite/external/ounit-1.1.2
+/testsuite/external/paounit
+/testsuite/external/pa_ounit-109.36.00
+/testsuite/external/pcre
+/testsuite/external/pcre-ocaml-6.2.5
+/testsuite/external/pipebang
+/testsuite/external/pipebang-109.28.00
+/testsuite/external/react
+/testsuite/external/react-0.9.3
+/testsuite/external/res
+/testsuite/external/res-3.2.0
+/testsuite/external/rss
+/testsuite/external/ocamlrss-2.2.2
+/testsuite/external/sexplib
+/testsuite/external/sexplib-109.15.00
+/testsuite/external/sks
+/testsuite/external/sks-1.1.3
+/testsuite/external/sqlite
+/testsuite/external/sqlite3-ocaml-2.0.1
+/testsuite/external/textutils
+/testsuite/external/textutils-109.36.00
+/testsuite/external/typeconv
+/testsuite/external/type_conv-109.28.00
+/testsuite/external/unison
+/testsuite/external/unison-2.45.4
+/testsuite/external/variantslib
+/testsuite/external/variantslib-109.15.00
+/testsuite/external/vsyml
+/testsuite/external/vsyml-2010-04-06
+/testsuite/external/xmllight
+/testsuite/external/xml-light.2.3
+/testsuite/external/xmlm
+/testsuite/external/xmlm-1.1.0
+/testsuite/external/zarith
+/testsuite/external/zarith-1.2.1
+/testsuite/external/zen
+/testsuite/external/zen_2.3.2
+/testsuite/external/._ZEN_2.3.2
+
+# /testsuite/interactive/
+/testsuite/interactive/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/interactive/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/interactive/_log
+/testsuite/interactive/*.so
+/testsuite/interactive/*.a
+/testsuite/interactive/*.result
+/testsuite/interactive/*.byte
+/testsuite/interactive/*.native
+/testsuite/interactive/program
+/testsuite/interactive/*.cm*
+/testsuite/interactive/*.o
+
+# /testsuite/interactive/lib-gc/
+/testsuite/interactive/lib-gc/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/interactive/lib-gc/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/interactive/lib-gc/_log
+/testsuite/interactive/lib-gc/*.so
+/testsuite/interactive/lib-gc/*.a
+/testsuite/interactive/lib-gc/*.result
+/testsuite/interactive/lib-gc/*.byte
+/testsuite/interactive/lib-gc/*.native
+/testsuite/interactive/lib-gc/program
+/testsuite/interactive/lib-gc/*.cm*
+/testsuite/interactive/lib-gc/*.o
+
+# /testsuite/interactive/lib-graph/
+/testsuite/interactive/lib-graph/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/interactive/lib-graph/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/interactive/lib-graph/_log
+/testsuite/interactive/lib-graph/*.so
+/testsuite/interactive/lib-graph/*.a
+/testsuite/interactive/lib-graph/*.result
+/testsuite/interactive/lib-graph/*.byte
+/testsuite/interactive/lib-graph/*.native
+/testsuite/interactive/lib-graph/program
+/testsuite/interactive/lib-graph/*.cm*
+/testsuite/interactive/lib-graph/*.o
+
+# /testsuite/interactive/lib-graph-2/
+/testsuite/interactive/lib-graph-2/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/interactive/lib-graph-2/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/interactive/lib-graph-2/_log
+/testsuite/interactive/lib-graph-2/*.so
+/testsuite/interactive/lib-graph-2/*.a
+/testsuite/interactive/lib-graph-2/*.result
+/testsuite/interactive/lib-graph-2/*.byte
+/testsuite/interactive/lib-graph-2/*.native
+/testsuite/interactive/lib-graph-2/program
+/testsuite/interactive/lib-graph-2/*.cm*
+/testsuite/interactive/lib-graph-2/*.o
+
+# /testsuite/interactive/lib-graph-3/
+/testsuite/interactive/lib-graph-3/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/interactive/lib-graph-3/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/interactive/lib-graph-3/_log
+/testsuite/interactive/lib-graph-3/*.so
+/testsuite/interactive/lib-graph-3/*.a
+/testsuite/interactive/lib-graph-3/*.result
+/testsuite/interactive/lib-graph-3/*.byte
+/testsuite/interactive/lib-graph-3/*.native
+/testsuite/interactive/lib-graph-3/program
+/testsuite/interactive/lib-graph-3/*.cm*
+/testsuite/interactive/lib-graph-3/*.o
+
+# /testsuite/interactive/lib-signals/
+/testsuite/interactive/lib-signals/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/interactive/lib-signals/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/interactive/lib-signals/_log
+/testsuite/interactive/lib-signals/*.so
+/testsuite/interactive/lib-signals/*.a
+/testsuite/interactive/lib-signals/*.result
+/testsuite/interactive/lib-signals/*.byte
+/testsuite/interactive/lib-signals/*.native
+/testsuite/interactive/lib-signals/program
+/testsuite/interactive/lib-signals/*.cm*
+/testsuite/interactive/lib-signals/*.o
+
+# /testsuite/lib/
+/testsuite/lib/*.o
+/testsuite/lib/*.a
+/testsuite/lib/*.so
+/testsuite/lib/*.obj
+/testsuite/lib/*.dll
+/testsuite/lib/*.cm[ioxat]
+/testsuite/lib/*.cmx[as]
+/testsuite/lib/*.cmti
+/testsuite/lib/*.annot
+/testsuite/lib/*.result
+/testsuite/lib/*.byte
+/testsuite/lib/*.native
+/testsuite/lib/program
+/testsuite/lib/*.exe
+/testsuite/lib/.depend
+/testsuite/lib/.depend.nt
+/testsuite/lib/.DS_Store
+
+# /testsuite/makefiles/
+/testsuite/makefiles/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/makefiles/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/makefiles/_log
+/testsuite/makefiles/*.so
+/testsuite/makefiles/*.a
+/testsuite/makefiles/*.result
+/testsuite/makefiles/*.byte
+/testsuite/makefiles/*.native
+/testsuite/makefiles/program
+/testsuite/makefiles/*.cm*
+/testsuite/makefiles/*.o
+
+# /testsuite/tests/
+/testsuite/tests/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/tests/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/tests/_log
+/testsuite/tests/*.so
+/testsuite/tests/*.a
+/testsuite/tests/*.result
+/testsuite/tests/*.byte
+/testsuite/tests/*.native
+/testsuite/tests/program
+/testsuite/tests/*.cm*
+/testsuite/tests/*.o
+
+# /testsuite/tests/asmcomp/
+/testsuite/tests/asmcomp/*.o
+/testsuite/tests/asmcomp/*.a
+/testsuite/tests/asmcomp/*.so
+/testsuite/tests/asmcomp/*.obj
+/testsuite/tests/asmcomp/*.lib
+/testsuite/tests/asmcomp/*.dll
+/testsuite/tests/asmcomp/*.cm[ioxat]
+/testsuite/tests/asmcomp/*.cmx[as]
+/testsuite/tests/asmcomp/*.cmti
+/testsuite/tests/asmcomp/*.annot
+/testsuite/tests/asmcomp/*.result
+/testsuite/tests/asmcomp/*.byte
+/testsuite/tests/asmcomp/*.native
+/testsuite/tests/asmcomp/program
+/testsuite/tests/asmcomp/*.exe
+/testsuite/tests/asmcomp/*.exe.manifest
+/testsuite/tests/asmcomp/.depend
+/testsuite/tests/asmcomp/.depend.nt
+/testsuite/tests/asmcomp/.DS_Store
+/testsuite/tests/asmcomp/codegen
+/testsuite/tests/asmcomp/parsecmm.ml
+/testsuite/tests/asmcomp/parsecmm.mli
+/testsuite/tests/asmcomp/lexcmm.ml
+/testsuite/tests/asmcomp/*.s
+/testsuite/tests/asmcomp/*.out
+/testsuite/tests/asmcomp/*.out.dSYM
+
+# /testsuite/tests/backtrace/
+/testsuite/tests/backtrace/*.o
+/testsuite/tests/backtrace/*.a
+/testsuite/tests/backtrace/*.so
+/testsuite/tests/backtrace/*.obj
+/testsuite/tests/backtrace/*.lib
+/testsuite/tests/backtrace/*.dll
+/testsuite/tests/backtrace/*.cm[ioxat]
+/testsuite/tests/backtrace/*.cmx[as]
+/testsuite/tests/backtrace/*.cmti
+/testsuite/tests/backtrace/*.annot
+/testsuite/tests/backtrace/*.result
+/testsuite/tests/backtrace/*.byte
+/testsuite/tests/backtrace/*.native
+/testsuite/tests/backtrace/program
+/testsuite/tests/backtrace/*.exe
+/testsuite/tests/backtrace/*.exe.manifest
+/testsuite/tests/backtrace/.depend
+/testsuite/tests/backtrace/.depend.nt
+/testsuite/tests/backtrace/.DS_Store
+
+# /testsuite/tests/basic/
+/testsuite/tests/basic/*.o
+/testsuite/tests/basic/*.a
+/testsuite/tests/basic/*.so
+/testsuite/tests/basic/*.obj
+/testsuite/tests/basic/*.cm[ioxa]
+/testsuite/tests/basic/*.cmx[as]
+/testsuite/tests/basic/*.annot
+/testsuite/tests/basic/*.result
+/testsuite/tests/basic/*.byte
+/testsuite/tests/basic/*.native
+/testsuite/tests/basic/program
+/testsuite/tests/basic/program.exe
+/testsuite/tests/basic/.depend
+/testsuite/tests/basic/.depend.nt
+/testsuite/tests/basic/.DS_Store
+
+# /testsuite/tests/basic-float/
+/testsuite/tests/basic-float/*.o
+/testsuite/tests/basic-float/*.a
+/testsuite/tests/basic-float/*.so
+/testsuite/tests/basic-float/*.obj
+/testsuite/tests/basic-float/*.lib
+/testsuite/tests/basic-float/*.dll
+/testsuite/tests/basic-float/*.cm[ioxat]
+/testsuite/tests/basic-float/*.cmx[as]
+/testsuite/tests/basic-float/*.cmti
+/testsuite/tests/basic-float/*.annot
+/testsuite/tests/basic-float/*.result
+/testsuite/tests/basic-float/*.byte
+/testsuite/tests/basic-float/*.native
+/testsuite/tests/basic-float/program
+/testsuite/tests/basic-float/*.exe
+/testsuite/tests/basic-float/*.exe.manifest
+/testsuite/tests/basic-float/.depend
+/testsuite/tests/basic-float/.depend.nt
+/testsuite/tests/basic-float/.DS_Store
+
+# /testsuite/tests/basic-io/
+/testsuite/tests/basic-io/*.o
+/testsuite/tests/basic-io/*.a
+/testsuite/tests/basic-io/*.so
+/testsuite/tests/basic-io/*.obj
+/testsuite/tests/basic-io/*.lib
+/testsuite/tests/basic-io/*.dll
+/testsuite/tests/basic-io/*.cm[ioxat]
+/testsuite/tests/basic-io/*.cmx[as]
+/testsuite/tests/basic-io/*.cmti
+/testsuite/tests/basic-io/*.annot
+/testsuite/tests/basic-io/*.result
+/testsuite/tests/basic-io/*.byte
+/testsuite/tests/basic-io/*.native
+/testsuite/tests/basic-io/program
+/testsuite/tests/basic-io/*.exe
+/testsuite/tests/basic-io/*.exe.manifest
+/testsuite/tests/basic-io/.depend
+/testsuite/tests/basic-io/.depend.nt
+/testsuite/tests/basic-io/.DS_Store
+
+# /testsuite/tests/basic-io-2/
+/testsuite/tests/basic-io-2/*.o
+/testsuite/tests/basic-io-2/*.a
+/testsuite/tests/basic-io-2/*.so
+/testsuite/tests/basic-io-2/*.obj
+/testsuite/tests/basic-io-2/*.lib
+/testsuite/tests/basic-io-2/*.dll
+/testsuite/tests/basic-io-2/*.cm[ioxat]
+/testsuite/tests/basic-io-2/*.cmx[as]
+/testsuite/tests/basic-io-2/*.cmti
+/testsuite/tests/basic-io-2/*.annot
+/testsuite/tests/basic-io-2/*.result
+/testsuite/tests/basic-io-2/*.byte
+/testsuite/tests/basic-io-2/*.native
+/testsuite/tests/basic-io-2/program
+/testsuite/tests/basic-io-2/*.exe
+/testsuite/tests/basic-io-2/*.exe.manifest
+/testsuite/tests/basic-io-2/.depend
+/testsuite/tests/basic-io-2/.depend.nt
+/testsuite/tests/basic-io-2/.DS_Store
+
+# /testsuite/tests/basic-manyargs/
+/testsuite/tests/basic-manyargs/*.o
+/testsuite/tests/basic-manyargs/*.a
+/testsuite/tests/basic-manyargs/*.so
+/testsuite/tests/basic-manyargs/*.obj
+/testsuite/tests/basic-manyargs/*.lib
+/testsuite/tests/basic-manyargs/*.dll
+/testsuite/tests/basic-manyargs/*.cm[ioxat]
+/testsuite/tests/basic-manyargs/*.cmx[as]
+/testsuite/tests/basic-manyargs/*.cmti
+/testsuite/tests/basic-manyargs/*.annot
+/testsuite/tests/basic-manyargs/*.result
+/testsuite/tests/basic-manyargs/*.byte
+/testsuite/tests/basic-manyargs/*.native
+/testsuite/tests/basic-manyargs/program
+/testsuite/tests/basic-manyargs/*.exe
+/testsuite/tests/basic-manyargs/*.exe.manifest
+/testsuite/tests/basic-manyargs/.depend
+/testsuite/tests/basic-manyargs/.depend.nt
+/testsuite/tests/basic-manyargs/.DS_Store
+
+# /testsuite/tests/basic-more/
+/testsuite/tests/basic-more/*.o
+/testsuite/tests/basic-more/*.a
+/testsuite/tests/basic-more/*.so
+/testsuite/tests/basic-more/*.obj
+/testsuite/tests/basic-more/*.cm[ioxa]
+/testsuite/tests/basic-more/*.cmx[as]
+/testsuite/tests/basic-more/*.annot
+/testsuite/tests/basic-more/*.result
+/testsuite/tests/basic-more/*.byte
+/testsuite/tests/basic-more/*.native
+/testsuite/tests/basic-more/program
+/testsuite/tests/basic-more/program.exe
+/testsuite/tests/basic-more/.depend
+/testsuite/tests/basic-more/.depend.nt
+/testsuite/tests/basic-more/.DS_Store
+
+# /testsuite/tests/basic-multdef/
+/testsuite/tests/basic-multdef/*.o
+/testsuite/tests/basic-multdef/*.a
+/testsuite/tests/basic-multdef/*.so
+/testsuite/tests/basic-multdef/*.obj
+/testsuite/tests/basic-multdef/*.lib
+/testsuite/tests/basic-multdef/*.dll
+/testsuite/tests/basic-multdef/*.cm[ioxat]
+/testsuite/tests/basic-multdef/*.cmx[as]
+/testsuite/tests/basic-multdef/*.cmti
+/testsuite/tests/basic-multdef/*.annot
+/testsuite/tests/basic-multdef/*.result
+/testsuite/tests/basic-multdef/*.byte
+/testsuite/tests/basic-multdef/*.native
+/testsuite/tests/basic-multdef/program
+/testsuite/tests/basic-multdef/*.exe
+/testsuite/tests/basic-multdef/*.exe.manifest
+/testsuite/tests/basic-multdef/.depend
+/testsuite/tests/basic-multdef/.depend.nt
+/testsuite/tests/basic-multdef/.DS_Store
+
+# /testsuite/tests/basic-private/
+/testsuite/tests/basic-private/*.o
+/testsuite/tests/basic-private/*.a
+/testsuite/tests/basic-private/*.so
+/testsuite/tests/basic-private/*.obj
+/testsuite/tests/basic-private/*.lib
+/testsuite/tests/basic-private/*.dll
+/testsuite/tests/basic-private/*.cm[ioxat]
+/testsuite/tests/basic-private/*.cmx[as]
+/testsuite/tests/basic-private/*.cmti
+/testsuite/tests/basic-private/*.annot
+/testsuite/tests/basic-private/*.result
+/testsuite/tests/basic-private/*.byte
+/testsuite/tests/basic-private/*.native
+/testsuite/tests/basic-private/program
+/testsuite/tests/basic-private/*.exe
+/testsuite/tests/basic-private/*.exe.manifest
+/testsuite/tests/basic-private/.depend
+/testsuite/tests/basic-private/.depend.nt
+/testsuite/tests/basic-private/.DS_Store
+
+# /testsuite/tests/callback/
+/testsuite/tests/callback/*.o
+/testsuite/tests/callback/*.a
+/testsuite/tests/callback/*.so
+/testsuite/tests/callback/*.obj
+/testsuite/tests/callback/*.cm[ioxa]
+/testsuite/tests/callback/*.cmx[as]
+/testsuite/tests/callback/*.annot
+/testsuite/tests/callback/*.result
+/testsuite/tests/callback/*.byte
+/testsuite/tests/callback/*.native
+/testsuite/tests/callback/program
+/testsuite/tests/callback/program.exe
+/testsuite/tests/callback/.depend
+/testsuite/tests/callback/.depend.nt
+/testsuite/tests/callback/.DS_Store
+
+# /testsuite/tests/embedded/
+/testsuite/tests/embedded/*.o
+/testsuite/tests/embedded/*.a
+/testsuite/tests/embedded/*.so
+/testsuite/tests/embedded/*.obj
+/testsuite/tests/embedded/*.lib
+/testsuite/tests/embedded/*.dll
+/testsuite/tests/embedded/*.cm[ioxat]
+/testsuite/tests/embedded/*.cmx[as]
+/testsuite/tests/embedded/*.cmti
+/testsuite/tests/embedded/*.annot
+/testsuite/tests/embedded/*.result
+/testsuite/tests/embedded/*.byte
+/testsuite/tests/embedded/*.native
+/testsuite/tests/embedded/program
+/testsuite/tests/embedded/*.exe
+/testsuite/tests/embedded/*.exe.manifest
+/testsuite/tests/embedded/.depend
+/testsuite/tests/embedded/.depend.nt
+/testsuite/tests/embedded/.DS_Store
+/testsuite/tests/embedded/caml
+
+# /testsuite/tests/exotic-syntax/
+/testsuite/tests/exotic-syntax/*.o
+/testsuite/tests/exotic-syntax/*.a
+/testsuite/tests/exotic-syntax/*.so
+/testsuite/tests/exotic-syntax/*.obj
+/testsuite/tests/exotic-syntax/*.lib
+/testsuite/tests/exotic-syntax/*.dll
+/testsuite/tests/exotic-syntax/*.cm[ioxat]
+/testsuite/tests/exotic-syntax/*.cmx[as]
+/testsuite/tests/exotic-syntax/*.cmti
+/testsuite/tests/exotic-syntax/*.annot
+/testsuite/tests/exotic-syntax/*.result
+/testsuite/tests/exotic-syntax/*.byte
+/testsuite/tests/exotic-syntax/*.native
+/testsuite/tests/exotic-syntax/program
+/testsuite/tests/exotic-syntax/*.exe
+/testsuite/tests/exotic-syntax/*.exe.manifest
+/testsuite/tests/exotic-syntax/.depend
+/testsuite/tests/exotic-syntax/.depend.nt
+/testsuite/tests/exotic-syntax/.DS_Store
+
+# /testsuite/tests/gc-roots/
+/testsuite/tests/gc-roots/*.o
+/testsuite/tests/gc-roots/*.a
+/testsuite/tests/gc-roots/*.so
+/testsuite/tests/gc-roots/*.obj
+/testsuite/tests/gc-roots/*.lib
+/testsuite/tests/gc-roots/*.dll
+/testsuite/tests/gc-roots/*.cm[ioxat]
+/testsuite/tests/gc-roots/*.cmx[as]
+/testsuite/tests/gc-roots/*.cmti
+/testsuite/tests/gc-roots/*.annot
+/testsuite/tests/gc-roots/*.result
+/testsuite/tests/gc-roots/*.byte
+/testsuite/tests/gc-roots/*.native
+/testsuite/tests/gc-roots/program
+/testsuite/tests/gc-roots/*.exe
+/testsuite/tests/gc-roots/*.exe.manifest
+/testsuite/tests/gc-roots/.depend
+/testsuite/tests/gc-roots/.depend.nt
+/testsuite/tests/gc-roots/.DS_Store
+
+# /testsuite/tests/letrec/
+/testsuite/tests/letrec/*.o
+/testsuite/tests/letrec/*.a
+/testsuite/tests/letrec/*.so
+/testsuite/tests/letrec/*.obj
+/testsuite/tests/letrec/*.cm[ioxa]
+/testsuite/tests/letrec/*.cmx[as]
+/testsuite/tests/letrec/*.annot
+/testsuite/tests/letrec/*.result
+/testsuite/tests/letrec/*.byte
+/testsuite/tests/letrec/*.native
+/testsuite/tests/letrec/program
+/testsuite/tests/letrec/program.exe
+/testsuite/tests/letrec/.depend
+/testsuite/tests/letrec/.depend.nt
+/testsuite/tests/letrec/.DS_Store
+
+# /testsuite/tests/lib-bigarray/
+/testsuite/tests/lib-bigarray/*.o
+/testsuite/tests/lib-bigarray/*.a
+/testsuite/tests/lib-bigarray/*.so
+/testsuite/tests/lib-bigarray/*.obj
+/testsuite/tests/lib-bigarray/*.lib
+/testsuite/tests/lib-bigarray/*.dll
+/testsuite/tests/lib-bigarray/*.cm[ioxat]
+/testsuite/tests/lib-bigarray/*.cmx[as]
+/testsuite/tests/lib-bigarray/*.cmti
+/testsuite/tests/lib-bigarray/*.annot
+/testsuite/tests/lib-bigarray/*.result
+/testsuite/tests/lib-bigarray/*.byte
+/testsuite/tests/lib-bigarray/*.native
+/testsuite/tests/lib-bigarray/program
+/testsuite/tests/lib-bigarray/*.exe
+/testsuite/tests/lib-bigarray/*.exe.manifest
+/testsuite/tests/lib-bigarray/.depend
+/testsuite/tests/lib-bigarray/.depend.nt
+/testsuite/tests/lib-bigarray/.DS_Store
+
+# /testsuite/tests/lib-bigarray-2/
+/testsuite/tests/lib-bigarray-2/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/tests/lib-bigarray-2/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/tests/lib-bigarray-2/_log
+/testsuite/tests/lib-bigarray-2/*.so
+/testsuite/tests/lib-bigarray-2/*.a
+/testsuite/tests/lib-bigarray-2/*.result
+/testsuite/tests/lib-bigarray-2/*.byte
+/testsuite/tests/lib-bigarray-2/*.native
+/testsuite/tests/lib-bigarray-2/program
+/testsuite/tests/lib-bigarray-2/*.cm*
+/testsuite/tests/lib-bigarray-2/*.o
+
+# /testsuite/tests/lib-digest/
+/testsuite/tests/lib-digest/*.o
+/testsuite/tests/lib-digest/*.a
+/testsuite/tests/lib-digest/*.so
+/testsuite/tests/lib-digest/*.obj
+/testsuite/tests/lib-digest/*.lib
+/testsuite/tests/lib-digest/*.dll
+/testsuite/tests/lib-digest/*.cm[ioxat]
+/testsuite/tests/lib-digest/*.cmx[as]
+/testsuite/tests/lib-digest/*.cmti
+/testsuite/tests/lib-digest/*.annot
+/testsuite/tests/lib-digest/*.result
+/testsuite/tests/lib-digest/*.byte
+/testsuite/tests/lib-digest/*.native
+/testsuite/tests/lib-digest/program
+/testsuite/tests/lib-digest/*.exe
+/testsuite/tests/lib-digest/*.exe.manifest
+/testsuite/tests/lib-digest/.depend
+/testsuite/tests/lib-digest/.depend.nt
+/testsuite/tests/lib-digest/.DS_Store
+
+# /testsuite/tests/lib-dynlink-bytecode/
+/testsuite/tests/lib-dynlink-bytecode/*.o
+/testsuite/tests/lib-dynlink-bytecode/*.a
+/testsuite/tests/lib-dynlink-bytecode/*.so
+/testsuite/tests/lib-dynlink-bytecode/*.obj
+/testsuite/tests/lib-dynlink-bytecode/*.lib
+/testsuite/tests/lib-dynlink-bytecode/*.dll
+/testsuite/tests/lib-dynlink-bytecode/*.cm[ioxat]
+/testsuite/tests/lib-dynlink-bytecode/*.cmx[as]
+/testsuite/tests/lib-dynlink-bytecode/*.cmti
+/testsuite/tests/lib-dynlink-bytecode/*.annot
+/testsuite/tests/lib-dynlink-bytecode/*.result
+/testsuite/tests/lib-dynlink-bytecode/*.byte
+/testsuite/tests/lib-dynlink-bytecode/*.native
+/testsuite/tests/lib-dynlink-bytecode/program
+/testsuite/tests/lib-dynlink-bytecode/*.exe
+/testsuite/tests/lib-dynlink-bytecode/*.exe.manifest
+/testsuite/tests/lib-dynlink-bytecode/.depend
+/testsuite/tests/lib-dynlink-bytecode/.depend.nt
+/testsuite/tests/lib-dynlink-bytecode/.DS_Store
+/testsuite/tests/lib-dynlink-bytecode/main
+/testsuite/tests/lib-dynlink-bytecode/static
+/testsuite/tests/lib-dynlink-bytecode/custom
+/testsuite/tests/lib-dynlink-bytecode/custom.exe
+/testsuite/tests/lib-dynlink-bytecode/marshal.data
+/testsuite/tests/lib-dynlink-bytecode/caml
+
+# /testsuite/tests/lib-dynlink-csharp/
+/testsuite/tests/lib-dynlink-csharp/*.o
+/testsuite/tests/lib-dynlink-csharp/*.a
+/testsuite/tests/lib-dynlink-csharp/*.so
+/testsuite/tests/lib-dynlink-csharp/*.obj
+/testsuite/tests/lib-dynlink-csharp/*.lib
+/testsuite/tests/lib-dynlink-csharp/*.dll
+/testsuite/tests/lib-dynlink-csharp/*.cm[ioxat]
+/testsuite/tests/lib-dynlink-csharp/*.cmx[as]
+/testsuite/tests/lib-dynlink-csharp/*.cmti
+/testsuite/tests/lib-dynlink-csharp/*.annot
+/testsuite/tests/lib-dynlink-csharp/*.result
+/testsuite/tests/lib-dynlink-csharp/*.byte
+/testsuite/tests/lib-dynlink-csharp/*.native
+/testsuite/tests/lib-dynlink-csharp/program
+/testsuite/tests/lib-dynlink-csharp/*.exe
+/testsuite/tests/lib-dynlink-csharp/*.exe.manifest
+/testsuite/tests/lib-dynlink-csharp/.depend
+/testsuite/tests/lib-dynlink-csharp/.depend.nt
+/testsuite/tests/lib-dynlink-csharp/.DS_Store
+
+# /testsuite/tests/lib-dynlink-native/
+/testsuite/tests/lib-dynlink-native/*.o
+/testsuite/tests/lib-dynlink-native/*.a
+/testsuite/tests/lib-dynlink-native/*.so
+/testsuite/tests/lib-dynlink-native/*.obj
+/testsuite/tests/lib-dynlink-native/*.lib
+/testsuite/tests/lib-dynlink-native/*.dll
+/testsuite/tests/lib-dynlink-native/*.cm[ioxat]
+/testsuite/tests/lib-dynlink-native/*.cmx[as]
+/testsuite/tests/lib-dynlink-native/*.cmti
+/testsuite/tests/lib-dynlink-native/*.annot
+/testsuite/tests/lib-dynlink-native/*.result
+/testsuite/tests/lib-dynlink-native/*.byte
+/testsuite/tests/lib-dynlink-native/*.native
+/testsuite/tests/lib-dynlink-native/program
+/testsuite/tests/lib-dynlink-native/*.exe
+/testsuite/tests/lib-dynlink-native/*.exe.manifest
+/testsuite/tests/lib-dynlink-native/.depend
+/testsuite/tests/lib-dynlink-native/.depend.nt
+/testsuite/tests/lib-dynlink-native/.DS_Store
+/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/main.exe
+/testsuite/tests/lib-dynlink-native/marshal.data
+/testsuite/tests/lib-dynlink-native/caml
+
+# /testsuite/tests/lib-dynlink-native/sub/
+/testsuite/tests/lib-dynlink-native/sub/*.o
+/testsuite/tests/lib-dynlink-native/sub/*.a
+/testsuite/tests/lib-dynlink-native/sub/*.so
+/testsuite/tests/lib-dynlink-native/sub/*.obj
+/testsuite/tests/lib-dynlink-native/sub/*.lib
+/testsuite/tests/lib-dynlink-native/sub/*.dll
+/testsuite/tests/lib-dynlink-native/sub/*.cm[ioxat]
+/testsuite/tests/lib-dynlink-native/sub/*.cmx[as]
+/testsuite/tests/lib-dynlink-native/sub/*.cmti
+/testsuite/tests/lib-dynlink-native/sub/*.annot
+/testsuite/tests/lib-dynlink-native/sub/*.result
+/testsuite/tests/lib-dynlink-native/sub/*.byte
+/testsuite/tests/lib-dynlink-native/sub/*.native
+/testsuite/tests/lib-dynlink-native/sub/program
+/testsuite/tests/lib-dynlink-native/sub/*.exe
+/testsuite/tests/lib-dynlink-native/sub/*.exe.manifest
+/testsuite/tests/lib-dynlink-native/sub/.depend
+/testsuite/tests/lib-dynlink-native/sub/.depend.nt
+/testsuite/tests/lib-dynlink-native/sub/.DS_Store
+
+# /testsuite/tests/lib-format/
+/testsuite/tests/lib-format/*.o
+/testsuite/tests/lib-format/*.a
+/testsuite/tests/lib-format/*.so
+/testsuite/tests/lib-format/*.obj
+/testsuite/tests/lib-format/*.lib
+/testsuite/tests/lib-format/*.dll
+/testsuite/tests/lib-format/*.cm[ioxat]
+/testsuite/tests/lib-format/*.cmx[as]
+/testsuite/tests/lib-format/*.cmti
+/testsuite/tests/lib-format/*.annot
+/testsuite/tests/lib-format/*.result
+/testsuite/tests/lib-format/*.byte
+/testsuite/tests/lib-format/*.native
+/testsuite/tests/lib-format/program
+/testsuite/tests/lib-format/*.exe
+/testsuite/tests/lib-format/*.exe.manifest
+/testsuite/tests/lib-format/.depend
+/testsuite/tests/lib-format/.depend.nt
+/testsuite/tests/lib-format/.DS_Store
+
+# /testsuite/tests/lib-hashtbl/
+/testsuite/tests/lib-hashtbl/*.o
+/testsuite/tests/lib-hashtbl/*.a
+/testsuite/tests/lib-hashtbl/*.so
+/testsuite/tests/lib-hashtbl/*.obj
+/testsuite/tests/lib-hashtbl/*.cm[ioxa]
+/testsuite/tests/lib-hashtbl/*.cmx[as]
+/testsuite/tests/lib-hashtbl/*.annot
+/testsuite/tests/lib-hashtbl/*.result
+/testsuite/tests/lib-hashtbl/*.byte
+/testsuite/tests/lib-hashtbl/*.native
+/testsuite/tests/lib-hashtbl/program
+/testsuite/tests/lib-hashtbl/program.exe
+/testsuite/tests/lib-hashtbl/.depend
+/testsuite/tests/lib-hashtbl/.depend.nt
+/testsuite/tests/lib-hashtbl/.DS_Store
+
+# /testsuite/tests/lib-marshal/
+/testsuite/tests/lib-marshal/*.o
+/testsuite/tests/lib-marshal/*.a
+/testsuite/tests/lib-marshal/*.so
+/testsuite/tests/lib-marshal/*.obj
+/testsuite/tests/lib-marshal/*.lib
+/testsuite/tests/lib-marshal/*.dll
+/testsuite/tests/lib-marshal/*.cm[ioxat]
+/testsuite/tests/lib-marshal/*.cmx[as]
+/testsuite/tests/lib-marshal/*.cmti
+/testsuite/tests/lib-marshal/*.annot
+/testsuite/tests/lib-marshal/*.result
+/testsuite/tests/lib-marshal/*.byte
+/testsuite/tests/lib-marshal/*.native
+/testsuite/tests/lib-marshal/program
+/testsuite/tests/lib-marshal/*.exe
+/testsuite/tests/lib-marshal/*.exe.manifest
+/testsuite/tests/lib-marshal/.depend
+/testsuite/tests/lib-marshal/.depend.nt
+/testsuite/tests/lib-marshal/.DS_Store
+
+# /testsuite/tests/lib-num/
+/testsuite/tests/lib-num/*.o
+/testsuite/tests/lib-num/*.a
+/testsuite/tests/lib-num/*.so
+/testsuite/tests/lib-num/*.obj
+/testsuite/tests/lib-num/*.lib
+/testsuite/tests/lib-num/*.dll
+/testsuite/tests/lib-num/*.cm[ioxat]
+/testsuite/tests/lib-num/*.cmx[as]
+/testsuite/tests/lib-num/*.cmti
+/testsuite/tests/lib-num/*.annot
+/testsuite/tests/lib-num/*.result
+/testsuite/tests/lib-num/*.byte
+/testsuite/tests/lib-num/*.native
+/testsuite/tests/lib-num/program
+/testsuite/tests/lib-num/*.exe
+/testsuite/tests/lib-num/*.exe.manifest
+/testsuite/tests/lib-num/.depend
+/testsuite/tests/lib-num/.depend.nt
+/testsuite/tests/lib-num/.DS_Store
+
+# /testsuite/tests/lib-num-2/
+/testsuite/tests/lib-num-2/*.o
+/testsuite/tests/lib-num-2/*.a
+/testsuite/tests/lib-num-2/*.so
+/testsuite/tests/lib-num-2/*.obj
+/testsuite/tests/lib-num-2/*.cm[ioxa]
+/testsuite/tests/lib-num-2/*.cmx[as]
+/testsuite/tests/lib-num-2/*.annot
+/testsuite/tests/lib-num-2/*.result
+/testsuite/tests/lib-num-2/*.byte
+/testsuite/tests/lib-num-2/*.native
+/testsuite/tests/lib-num-2/program
+/testsuite/tests/lib-num-2/program.exe
+/testsuite/tests/lib-num-2/.depend
+/testsuite/tests/lib-num-2/.depend.nt
+/testsuite/tests/lib-num-2/.DS_Store
+
+# /testsuite/tests/lib-printf/
+/testsuite/tests/lib-printf/*.o
+/testsuite/tests/lib-printf/*.a
+/testsuite/tests/lib-printf/*.so
+/testsuite/tests/lib-printf/*.obj
+/testsuite/tests/lib-printf/*.lib
+/testsuite/tests/lib-printf/*.dll
+/testsuite/tests/lib-printf/*.cm[ioxat]
+/testsuite/tests/lib-printf/*.cmx[as]
+/testsuite/tests/lib-printf/*.cmti
+/testsuite/tests/lib-printf/*.annot
+/testsuite/tests/lib-printf/*.result
+/testsuite/tests/lib-printf/*.byte
+/testsuite/tests/lib-printf/*.native
+/testsuite/tests/lib-printf/program
+/testsuite/tests/lib-printf/*.exe
+/testsuite/tests/lib-printf/*.exe.manifest
+/testsuite/tests/lib-printf/.depend
+/testsuite/tests/lib-printf/.depend.nt
+/testsuite/tests/lib-printf/.DS_Store
+
+# /testsuite/tests/lib-random/
+/testsuite/tests/lib-random/*.o
+/testsuite/tests/lib-random/*.a
+/testsuite/tests/lib-random/*.so
+/testsuite/tests/lib-random/*.obj
+/testsuite/tests/lib-random/*.lib
+/testsuite/tests/lib-random/*.dll
+/testsuite/tests/lib-random/*.cm[ioxat]
+/testsuite/tests/lib-random/*.cmx[as]
+/testsuite/tests/lib-random/*.cmti
+/testsuite/tests/lib-random/*.annot
+/testsuite/tests/lib-random/*.result
+/testsuite/tests/lib-random/*.byte
+/testsuite/tests/lib-random/*.native
+/testsuite/tests/lib-random/program
+/testsuite/tests/lib-random/*.exe
+/testsuite/tests/lib-random/*.exe.manifest
+/testsuite/tests/lib-random/.depend
+/testsuite/tests/lib-random/.depend.nt
+/testsuite/tests/lib-random/.DS_Store
+
+# /testsuite/tests/lib-scanf/
+/testsuite/tests/lib-scanf/*.o
+/testsuite/tests/lib-scanf/*.a
+/testsuite/tests/lib-scanf/*.so
+/testsuite/tests/lib-scanf/*.obj
+/testsuite/tests/lib-scanf/*.lib
+/testsuite/tests/lib-scanf/*.dll
+/testsuite/tests/lib-scanf/*.cm[ioxat]
+/testsuite/tests/lib-scanf/*.cmx[as]
+/testsuite/tests/lib-scanf/*.cmti
+/testsuite/tests/lib-scanf/*.annot
+/testsuite/tests/lib-scanf/*.result
+/testsuite/tests/lib-scanf/*.byte
+/testsuite/tests/lib-scanf/*.native
+/testsuite/tests/lib-scanf/program
+/testsuite/tests/lib-scanf/*.exe
+/testsuite/tests/lib-scanf/*.exe.manifest
+/testsuite/tests/lib-scanf/.depend
+/testsuite/tests/lib-scanf/.depend.nt
+/testsuite/tests/lib-scanf/.DS_Store
+/testsuite/tests/lib-scanf/tscanf_data
+
+# /testsuite/tests/lib-scanf-2/
+/testsuite/tests/lib-scanf-2/*.o
+/testsuite/tests/lib-scanf-2/*.a
+/testsuite/tests/lib-scanf-2/*.so
+/testsuite/tests/lib-scanf-2/*.obj
+/testsuite/tests/lib-scanf-2/*.lib
+/testsuite/tests/lib-scanf-2/*.dll
+/testsuite/tests/lib-scanf-2/*.cm[ioxat]
+/testsuite/tests/lib-scanf-2/*.cmx[as]
+/testsuite/tests/lib-scanf-2/*.cmti
+/testsuite/tests/lib-scanf-2/*.annot
+/testsuite/tests/lib-scanf-2/*.result
+/testsuite/tests/lib-scanf-2/*.byte
+/testsuite/tests/lib-scanf-2/*.native
+/testsuite/tests/lib-scanf-2/program
+/testsuite/tests/lib-scanf-2/*.exe
+/testsuite/tests/lib-scanf-2/*.exe.manifest
+/testsuite/tests/lib-scanf-2/.depend
+/testsuite/tests/lib-scanf-2/.depend.nt
+/testsuite/tests/lib-scanf-2/.DS_Store
+
+# /testsuite/tests/lib-set/
+/testsuite/tests/lib-set/*.o
+/testsuite/tests/lib-set/*.a
+/testsuite/tests/lib-set/*.so
+/testsuite/tests/lib-set/*.obj
+/testsuite/tests/lib-set/*.cm[ioxa]
+/testsuite/tests/lib-set/*.cmx[as]
+/testsuite/tests/lib-set/*.annot
+/testsuite/tests/lib-set/*.result
+/testsuite/tests/lib-set/*.byte
+/testsuite/tests/lib-set/*.native
+/testsuite/tests/lib-set/program
+/testsuite/tests/lib-set/program.exe
+/testsuite/tests/lib-set/.depend
+/testsuite/tests/lib-set/.depend.nt
+/testsuite/tests/lib-set/.DS_Store
+
+# /testsuite/tests/lib-str/
+/testsuite/tests/lib-str/*.o
+/testsuite/tests/lib-str/*.a
+/testsuite/tests/lib-str/*.so
+/testsuite/tests/lib-str/*.obj
+/testsuite/tests/lib-str/*.cm[ioxa]
+/testsuite/tests/lib-str/*.cmx[as]
+/testsuite/tests/lib-str/*.annot
+/testsuite/tests/lib-str/*.result
+/testsuite/tests/lib-str/*.byte
+/testsuite/tests/lib-str/*.native
+/testsuite/tests/lib-str/program
+/testsuite/tests/lib-str/program.exe
+/testsuite/tests/lib-str/.depend
+/testsuite/tests/lib-str/.depend.nt
+/testsuite/tests/lib-str/.DS_Store
+
+# /testsuite/tests/lib-stream/
+/testsuite/tests/lib-stream/*.o
+/testsuite/tests/lib-stream/*.a
+/testsuite/tests/lib-stream/*.so
+/testsuite/tests/lib-stream/*.obj
+/testsuite/tests/lib-stream/*.cm[ioxa]
+/testsuite/tests/lib-stream/*.cmx[as]
+/testsuite/tests/lib-stream/*.annot
+/testsuite/tests/lib-stream/*.result
+/testsuite/tests/lib-stream/*.byte
+/testsuite/tests/lib-stream/*.native
+/testsuite/tests/lib-stream/program
+/testsuite/tests/lib-stream/program.exe
+/testsuite/tests/lib-stream/.depend
+/testsuite/tests/lib-stream/.depend.nt
+/testsuite/tests/lib-stream/.DS_Store
+
+# /testsuite/tests/lib-systhreads/
+/testsuite/tests/lib-systhreads/*.o
+/testsuite/tests/lib-systhreads/*.a
+/testsuite/tests/lib-systhreads/*.so
+/testsuite/tests/lib-systhreads/*.obj
+/testsuite/tests/lib-systhreads/*.cm[ioxa]
+/testsuite/tests/lib-systhreads/*.cmx[as]
+/testsuite/tests/lib-systhreads/*.annot
+/testsuite/tests/lib-systhreads/*.result
+/testsuite/tests/lib-systhreads/*.byte
+/testsuite/tests/lib-systhreads/*.native
+/testsuite/tests/lib-systhreads/program
+/testsuite/tests/lib-systhreads/program.exe
+/testsuite/tests/lib-systhreads/.depend
+/testsuite/tests/lib-systhreads/.depend.nt
+/testsuite/tests/lib-systhreads/.DS_Store
+
+# /testsuite/tests/lib-threads/
+/testsuite/tests/lib-threads/*.o
+/testsuite/tests/lib-threads/*.a
+/testsuite/tests/lib-threads/*.so
+/testsuite/tests/lib-threads/*.obj
+/testsuite/tests/lib-threads/*.cm[ioxa]
+/testsuite/tests/lib-threads/*.cmx[as]
+/testsuite/tests/lib-threads/*.annot
+/testsuite/tests/lib-threads/*.result
+/testsuite/tests/lib-threads/*.byte
+/testsuite/tests/lib-threads/*.native
+/testsuite/tests/lib-threads/program
+/testsuite/tests/lib-threads/program.exe
+/testsuite/tests/lib-threads/.depend
+/testsuite/tests/lib-threads/.depend.nt
+/testsuite/tests/lib-threads/.DS_Store
+/testsuite/tests/lib-threads/*.byt
+
+# /testsuite/tests/misc/
+/testsuite/tests/misc/*.o
+/testsuite/tests/misc/*.a
+/testsuite/tests/misc/*.so
+/testsuite/tests/misc/*.obj
+/testsuite/tests/misc/*.cm[ioxa]
+/testsuite/tests/misc/*.cmx[as]
+/testsuite/tests/misc/*.annot
+/testsuite/tests/misc/*.result
+/testsuite/tests/misc/*.byte
+/testsuite/tests/misc/*.native
+/testsuite/tests/misc/program
+/testsuite/tests/misc/program.exe
+/testsuite/tests/misc/.depend
+/testsuite/tests/misc/.depend.nt
+/testsuite/tests/misc/.DS_Store
+
+# /testsuite/tests/misc-kb/
+/testsuite/tests/misc-kb/*.o
+/testsuite/tests/misc-kb/*.a
+/testsuite/tests/misc-kb/*.so
+/testsuite/tests/misc-kb/*.obj
+/testsuite/tests/misc-kb/*.lib
+/testsuite/tests/misc-kb/*.dll
+/testsuite/tests/misc-kb/*.cm[ioxat]
+/testsuite/tests/misc-kb/*.cmx[as]
+/testsuite/tests/misc-kb/*.cmti
+/testsuite/tests/misc-kb/*.annot
+/testsuite/tests/misc-kb/*.result
+/testsuite/tests/misc-kb/*.byte
+/testsuite/tests/misc-kb/*.native
+/testsuite/tests/misc-kb/program
+/testsuite/tests/misc-kb/*.exe
+/testsuite/tests/misc-kb/*.exe.manifest
+/testsuite/tests/misc-kb/.depend
+/testsuite/tests/misc-kb/.depend.nt
+/testsuite/tests/misc-kb/.DS_Store
+
+# /testsuite/tests/misc-unsafe/
+/testsuite/tests/misc-unsafe/*.o
+/testsuite/tests/misc-unsafe/*.a
+/testsuite/tests/misc-unsafe/*.so
+/testsuite/tests/misc-unsafe/*.obj
+/testsuite/tests/misc-unsafe/*.cm[ioxa]
+/testsuite/tests/misc-unsafe/*.cmx[as]
+/testsuite/tests/misc-unsafe/*.annot
+/testsuite/tests/misc-unsafe/*.result
+/testsuite/tests/misc-unsafe/*.byte
+/testsuite/tests/misc-unsafe/*.native
+/testsuite/tests/misc-unsafe/program
+/testsuite/tests/misc-unsafe/program.exe
+/testsuite/tests/misc-unsafe/.depend
+/testsuite/tests/misc-unsafe/.depend.nt
+/testsuite/tests/misc-unsafe/.DS_Store
+
+# /testsuite/tests/prim-bigstring/
+/testsuite/tests/prim-bigstring/*.o
+/testsuite/tests/prim-bigstring/*.a
+/testsuite/tests/prim-bigstring/*.so
+/testsuite/tests/prim-bigstring/*.obj
+/testsuite/tests/prim-bigstring/*.lib
+/testsuite/tests/prim-bigstring/*.dll
+/testsuite/tests/prim-bigstring/*.cm[ioxat]
+/testsuite/tests/prim-bigstring/*.cmx[as]
+/testsuite/tests/prim-bigstring/*.cmti
+/testsuite/tests/prim-bigstring/*.annot
+/testsuite/tests/prim-bigstring/*.result
+/testsuite/tests/prim-bigstring/*.byte
+/testsuite/tests/prim-bigstring/*.native
+/testsuite/tests/prim-bigstring/program
+/testsuite/tests/prim-bigstring/*.exe
+/testsuite/tests/prim-bigstring/*.exe.manifest
+/testsuite/tests/prim-bigstring/.depend
+/testsuite/tests/prim-bigstring/.depend.nt
+/testsuite/tests/prim-bigstring/.DS_Store
+
+# /testsuite/tests/prim-bswap/
+/testsuite/tests/prim-bswap/*.o
+/testsuite/tests/prim-bswap/*.a
+/testsuite/tests/prim-bswap/*.so
+/testsuite/tests/prim-bswap/*.obj
+/testsuite/tests/prim-bswap/*.cm[ioxat]
+/testsuite/tests/prim-bswap/*.cmx[as]
+/testsuite/tests/prim-bswap/*.cmti
+/testsuite/tests/prim-bswap/*.annot
+/testsuite/tests/prim-bswap/*.result
+/testsuite/tests/prim-bswap/*.byte
+/testsuite/tests/prim-bswap/*.native
+/testsuite/tests/prim-bswap/program
+/testsuite/tests/prim-bswap/program.exe
+/testsuite/tests/prim-bswap/.depend
+/testsuite/tests/prim-bswap/.depend.nt
+/testsuite/tests/prim-bswap/.DS_Store
+
+# /testsuite/tests/prim-revapply/
+/testsuite/tests/prim-revapply/*.o
+/testsuite/tests/prim-revapply/*.a
+/testsuite/tests/prim-revapply/*.so
+/testsuite/tests/prim-revapply/*.obj
+/testsuite/tests/prim-revapply/*.cm[ioxa]
+/testsuite/tests/prim-revapply/*.cmx[as]
+/testsuite/tests/prim-revapply/*.annot
+/testsuite/tests/prim-revapply/*.result
+/testsuite/tests/prim-revapply/*.byte
+/testsuite/tests/prim-revapply/*.native
+/testsuite/tests/prim-revapply/program
+/testsuite/tests/prim-revapply/program.exe
+/testsuite/tests/prim-revapply/.depend
+/testsuite/tests/prim-revapply/.depend.nt
+/testsuite/tests/prim-revapply/.DS_Store
+
+# /testsuite/tests/regression/pr5080-notes/
+/testsuite/tests/regression/pr5080-notes/*.o
+/testsuite/tests/regression/pr5080-notes/*.a
+/testsuite/tests/regression/pr5080-notes/*.so
+/testsuite/tests/regression/pr5080-notes/*.obj
+/testsuite/tests/regression/pr5080-notes/*.cm[ioxa]
+/testsuite/tests/regression/pr5080-notes/*.cmx[as]
+/testsuite/tests/regression/pr5080-notes/*.annot
+/testsuite/tests/regression/pr5080-notes/*.result
+/testsuite/tests/regression/pr5080-notes/*.byte
+/testsuite/tests/regression/pr5080-notes/*.native
+/testsuite/tests/regression/pr5080-notes/program
+/testsuite/tests/regression/pr5080-notes/program.exe
+/testsuite/tests/regression/pr5080-notes/.depend
+/testsuite/tests/regression/pr5080-notes/.depend.nt
+/testsuite/tests/regression/pr5080-notes/.DS_Store
+
+# /testsuite/tests/regression/pr5233/
+/testsuite/tests/regression/pr5233/*.o
+/testsuite/tests/regression/pr5233/*.a
+/testsuite/tests/regression/pr5233/*.so
+/testsuite/tests/regression/pr5233/*.obj
+/testsuite/tests/regression/pr5233/*.lib
+/testsuite/tests/regression/pr5233/*.dll
+/testsuite/tests/regression/pr5233/*.cm[ioxat]
+/testsuite/tests/regression/pr5233/*.cmx[as]
+/testsuite/tests/regression/pr5233/*.cmti
+/testsuite/tests/regression/pr5233/*.annot
+/testsuite/tests/regression/pr5233/*.result
+/testsuite/tests/regression/pr5233/*.byte
+/testsuite/tests/regression/pr5233/*.native
+/testsuite/tests/regression/pr5233/program
+/testsuite/tests/regression/pr5233/*.exe
+/testsuite/tests/regression/pr5233/*.exe.manifest
+/testsuite/tests/regression/pr5233/.depend
+/testsuite/tests/regression/pr5233/.depend.nt
+/testsuite/tests/regression/pr5233/.DS_Store
+
+# /testsuite/tests/regression/pr5757/
+/testsuite/tests/regression/pr5757/*.o
+/testsuite/tests/regression/pr5757/*.a
+/testsuite/tests/regression/pr5757/*.so
+/testsuite/tests/regression/pr5757/*.obj
+/testsuite/tests/regression/pr5757/*.lib
+/testsuite/tests/regression/pr5757/*.dll
+/testsuite/tests/regression/pr5757/*.cm[ioxat]
+/testsuite/tests/regression/pr5757/*.cmx[as]
+/testsuite/tests/regression/pr5757/*.cmti
+/testsuite/tests/regression/pr5757/*.annot
+/testsuite/tests/regression/pr5757/*.result
+/testsuite/tests/regression/pr5757/*.byte
+/testsuite/tests/regression/pr5757/*.native
+/testsuite/tests/regression/pr5757/program
+/testsuite/tests/regression/pr5757/*.exe
+/testsuite/tests/regression/pr5757/*.exe.manifest
+/testsuite/tests/regression/pr5757/.depend
+/testsuite/tests/regression/pr5757/.depend.nt
+/testsuite/tests/regression/pr5757/.DS_Store
+
+# /testsuite/tests/regression/pr6024/
+/testsuite/tests/regression/pr6024/*.o
+/testsuite/tests/regression/pr6024/*.a
+/testsuite/tests/regression/pr6024/*.so
+/testsuite/tests/regression/pr6024/*.obj
+/testsuite/tests/regression/pr6024/*.lib
+/testsuite/tests/regression/pr6024/*.dll
+/testsuite/tests/regression/pr6024/*.cm[ioxat]
+/testsuite/tests/regression/pr6024/*.cmx[as]
+/testsuite/tests/regression/pr6024/*.cmti
+/testsuite/tests/regression/pr6024/*.annot
+/testsuite/tests/regression/pr6024/*.result
+/testsuite/tests/regression/pr6024/*.byte
+/testsuite/tests/regression/pr6024/*.native
+/testsuite/tests/regression/pr6024/program
+/testsuite/tests/regression/pr6024/*.exe
+/testsuite/tests/regression/pr6024/*.exe.manifest
+/testsuite/tests/regression/pr6024/.depend
+/testsuite/tests/regression/pr6024/.depend.nt
+/testsuite/tests/regression/pr6024/.DS_Store
+
+# /testsuite/tests/runtime-errors/
+/testsuite/tests/runtime-errors/*.o
+/testsuite/tests/runtime-errors/*.a
+/testsuite/tests/runtime-errors/*.so
+/testsuite/tests/runtime-errors/*.obj
+/testsuite/tests/runtime-errors/*.lib
+/testsuite/tests/runtime-errors/*.dll
+/testsuite/tests/runtime-errors/*.cm[ioxat]
+/testsuite/tests/runtime-errors/*.cmx[as]
+/testsuite/tests/runtime-errors/*.cmti
+/testsuite/tests/runtime-errors/*.annot
+/testsuite/tests/runtime-errors/*.result
+/testsuite/tests/runtime-errors/*.byte
+/testsuite/tests/runtime-errors/*.native
+/testsuite/tests/runtime-errors/program
+/testsuite/tests/runtime-errors/*.exe
+/testsuite/tests/runtime-errors/*.exe.manifest
+/testsuite/tests/runtime-errors/.depend
+/testsuite/tests/runtime-errors/.depend.nt
+/testsuite/tests/runtime-errors/.DS_Store
+/testsuite/tests/runtime-errors/*.bytecode
+
+# /testsuite/tests/tool-debugger/
+/testsuite/tests/tool-debugger/*.o
+/testsuite/tests/tool-debugger/*.a
+/testsuite/tests/tool-debugger/*.so
+/testsuite/tests/tool-debugger/*.obj
+/testsuite/tests/tool-debugger/*.lib
+/testsuite/tests/tool-debugger/*.dll
+/testsuite/tests/tool-debugger/*.cm[ioxat]
+/testsuite/tests/tool-debugger/*.cmx[as]
+/testsuite/tests/tool-debugger/*.cmti
+/testsuite/tests/tool-debugger/*.annot
+/testsuite/tests/tool-debugger/*.result
+/testsuite/tests/tool-debugger/*.byte
+/testsuite/tests/tool-debugger/*.native
+/testsuite/tests/tool-debugger/program
+/testsuite/tests/tool-debugger/*.exe
+/testsuite/tests/tool-debugger/*.exe.manifest
+/testsuite/tests/tool-debugger/.depend
+/testsuite/tests/tool-debugger/.depend.nt
+/testsuite/tests/tool-debugger/.DS_Store
+/testsuite/tests/tool-debugger/compiler-libs
+
+# /testsuite/tests/tool-lexyacc/
+/testsuite/tests/tool-lexyacc/*.o
+/testsuite/tests/tool-lexyacc/*.a
+/testsuite/tests/tool-lexyacc/*.so
+/testsuite/tests/tool-lexyacc/*.obj
+/testsuite/tests/tool-lexyacc/*.lib
+/testsuite/tests/tool-lexyacc/*.dll
+/testsuite/tests/tool-lexyacc/*.cm[ioxat]
+/testsuite/tests/tool-lexyacc/*.cmx[as]
+/testsuite/tests/tool-lexyacc/*.cmti
+/testsuite/tests/tool-lexyacc/*.annot
+/testsuite/tests/tool-lexyacc/*.result
+/testsuite/tests/tool-lexyacc/*.byte
+/testsuite/tests/tool-lexyacc/*.native
+/testsuite/tests/tool-lexyacc/program
+/testsuite/tests/tool-lexyacc/*.exe
+/testsuite/tests/tool-lexyacc/*.exe.manifest
+/testsuite/tests/tool-lexyacc/.depend
+/testsuite/tests/tool-lexyacc/.depend.nt
+/testsuite/tests/tool-lexyacc/.DS_Store
+/testsuite/tests/tool-lexyacc/scanner.ml
+/testsuite/tests/tool-lexyacc/grammar.mli
+/testsuite/tests/tool-lexyacc/grammar.ml
+
+# /testsuite/tests/tool-ocaml/
+/testsuite/tests/tool-ocaml/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/tests/tool-ocaml/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/tests/tool-ocaml/_log
+/testsuite/tests/tool-ocaml/*.so
+/testsuite/tests/tool-ocaml/*.a
+/testsuite/tests/tool-ocaml/*.result
+/testsuite/tests/tool-ocaml/*.byte
+/testsuite/tests/tool-ocaml/*.native
+/testsuite/tests/tool-ocaml/program
+/testsuite/tests/tool-ocaml/*.cm*
+/testsuite/tests/tool-ocaml/*.o
+
+# /testsuite/tests/tool-ocamldoc/
+/testsuite/tests/tool-ocamldoc/*.o
+/testsuite/tests/tool-ocamldoc/*.a
+/testsuite/tests/tool-ocamldoc/*.so
+/testsuite/tests/tool-ocamldoc/*.obj
+/testsuite/tests/tool-ocamldoc/*.cm[ioxa]
+/testsuite/tests/tool-ocamldoc/*.cmx[as]
+/testsuite/tests/tool-ocamldoc/*.annot
+/testsuite/tests/tool-ocamldoc/*.result
+/testsuite/tests/tool-ocamldoc/*.byte
+/testsuite/tests/tool-ocamldoc/*.native
+/testsuite/tests/tool-ocamldoc/program
+/testsuite/tests/tool-ocamldoc/.depend
+/testsuite/tests/tool-ocamldoc/.depend.nt
+/testsuite/tests/tool-ocamldoc/.DS_Store
+/testsuite/tests/tool-ocamldoc/*.html
+/testsuite/tests/tool-ocamldoc/*.sty
+/testsuite/tests/tool-ocamldoc/*.css
+/testsuite/tests/tool-ocamldoc/ocamldoc.out
+
+# /testsuite/tests/typing-fstclassmod/
+/testsuite/tests/typing-fstclassmod/*.o
+/testsuite/tests/typing-fstclassmod/*.a
+/testsuite/tests/typing-fstclassmod/*.so
+/testsuite/tests/typing-fstclassmod/*.obj
+/testsuite/tests/typing-fstclassmod/*.lib
+/testsuite/tests/typing-fstclassmod/*.dll
+/testsuite/tests/typing-fstclassmod/*.cm[ioxat]
+/testsuite/tests/typing-fstclassmod/*.cmx[as]
+/testsuite/tests/typing-fstclassmod/*.cmti
+/testsuite/tests/typing-fstclassmod/*.annot
+/testsuite/tests/typing-fstclassmod/*.result
+/testsuite/tests/typing-fstclassmod/*.byte
+/testsuite/tests/typing-fstclassmod/*.native
+/testsuite/tests/typing-fstclassmod/program
+/testsuite/tests/typing-fstclassmod/*.exe
+/testsuite/tests/typing-fstclassmod/*.exe.manifest
+/testsuite/tests/typing-fstclassmod/.depend
+/testsuite/tests/typing-fstclassmod/.depend.nt
+/testsuite/tests/typing-fstclassmod/.DS_Store
+
+# /testsuite/tests/typing-gadts/
+/testsuite/tests/typing-gadts/*.o
+/testsuite/tests/typing-gadts/*.a
+/testsuite/tests/typing-gadts/*.so
+/testsuite/tests/typing-gadts/*.obj
+/testsuite/tests/typing-gadts/*.cm[ioxa]
+/testsuite/tests/typing-gadts/*.cmx[as]
+/testsuite/tests/typing-gadts/*.annot
+/testsuite/tests/typing-gadts/*.result
+/testsuite/tests/typing-gadts/*.byte
+/testsuite/tests/typing-gadts/*.native
+/testsuite/tests/typing-gadts/program
+/testsuite/tests/typing-gadts/.depend
+/testsuite/tests/typing-gadts/.depend.nt
+/testsuite/tests/typing-gadts/.DS_Store
+
+# /testsuite/tests/typing-implicit_unpack/
+/testsuite/tests/typing-implicit_unpack/*.o
+/testsuite/tests/typing-implicit_unpack/*.a
+/testsuite/tests/typing-implicit_unpack/*.so
+/testsuite/tests/typing-implicit_unpack/*.obj
+/testsuite/tests/typing-implicit_unpack/*.cm[ioxa]
+/testsuite/tests/typing-implicit_unpack/*.cmx[as]
+/testsuite/tests/typing-implicit_unpack/*.annot
+/testsuite/tests/typing-implicit_unpack/*.result
+/testsuite/tests/typing-implicit_unpack/*.byte
+/testsuite/tests/typing-implicit_unpack/*.native
+/testsuite/tests/typing-implicit_unpack/program
+/testsuite/tests/typing-implicit_unpack/.depend
+/testsuite/tests/typing-implicit_unpack/.depend.nt
+/testsuite/tests/typing-implicit_unpack/.DS_Store
+
+# /testsuite/tests/typing-labels/
+/testsuite/tests/typing-labels/*.o
+/testsuite/tests/typing-labels/*.a
+/testsuite/tests/typing-labels/*.so
+/testsuite/tests/typing-labels/*.obj
+/testsuite/tests/typing-labels/*.cm[ioxa]
+/testsuite/tests/typing-labels/*.cmx[as]
+/testsuite/tests/typing-labels/*.annot
+/testsuite/tests/typing-labels/*.result
+/testsuite/tests/typing-labels/*.byte
+/testsuite/tests/typing-labels/*.native
+/testsuite/tests/typing-labels/program
+/testsuite/tests/typing-labels/program.exe
+/testsuite/tests/typing-labels/.depend
+/testsuite/tests/typing-labels/.depend.nt
+/testsuite/tests/typing-labels/.DS_Store
+
+# /testsuite/tests/typing-misc/
+/testsuite/tests/typing-misc/*.o
+/testsuite/tests/typing-misc/*.a
+/testsuite/tests/typing-misc/*.so
+/testsuite/tests/typing-misc/*.obj
+/testsuite/tests/typing-misc/*.cm[ioxa]
+/testsuite/tests/typing-misc/*.cmx[as]
+/testsuite/tests/typing-misc/*.annot
+/testsuite/tests/typing-misc/*.result
+/testsuite/tests/typing-misc/*.byte
+/testsuite/tests/typing-misc/*.native
+/testsuite/tests/typing-misc/program
+/testsuite/tests/typing-misc/.depend
+/testsuite/tests/typing-misc/.depend.nt
+/testsuite/tests/typing-misc/.DS_Store
+
+# /testsuite/tests/typing-modules/
+/testsuite/tests/typing-modules/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/tests/typing-modules/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/tests/typing-modules/_log
+/testsuite/tests/typing-modules/*.so
+/testsuite/tests/typing-modules/*.a
+/testsuite/tests/typing-modules/*.result
+/testsuite/tests/typing-modules/*.byte
+/testsuite/tests/typing-modules/*.native
+/testsuite/tests/typing-modules/program
+
+# /testsuite/tests/typing-modules-bugs/
+/testsuite/tests/typing-modules-bugs/*.o
+/testsuite/tests/typing-modules-bugs/*.a
+/testsuite/tests/typing-modules-bugs/*.so
+/testsuite/tests/typing-modules-bugs/*.obj
+/testsuite/tests/typing-modules-bugs/*.cm[ioxa]
+/testsuite/tests/typing-modules-bugs/*.cmx[as]
+/testsuite/tests/typing-modules-bugs/*.annot
+/testsuite/tests/typing-modules-bugs/*.result
+/testsuite/tests/typing-modules-bugs/*.byte
+/testsuite/tests/typing-modules-bugs/*.native
+/testsuite/tests/typing-modules-bugs/program
+/testsuite/tests/typing-modules-bugs/program.exe
+/testsuite/tests/typing-modules-bugs/.depend
+/testsuite/tests/typing-modules-bugs/.depend.nt
+/testsuite/tests/typing-modules-bugs/.DS_Store
+
+# /testsuite/tests/typing-objects/
+/testsuite/tests/typing-objects/*.o
+/testsuite/tests/typing-objects/*.a
+/testsuite/tests/typing-objects/*.so
+/testsuite/tests/typing-objects/*.obj
+/testsuite/tests/typing-objects/*.cm[ioxa]
+/testsuite/tests/typing-objects/*.cmx[as]
+/testsuite/tests/typing-objects/*.annot
+/testsuite/tests/typing-objects/*.result
+/testsuite/tests/typing-objects/*.byte
+/testsuite/tests/typing-objects/*.native
+/testsuite/tests/typing-objects/program
+/testsuite/tests/typing-objects/.depend
+/testsuite/tests/typing-objects/.depend.nt
+/testsuite/tests/typing-objects/.DS_Store
+
+# /testsuite/tests/typing-objects-bugs/
+/testsuite/tests/typing-objects-bugs/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/tests/typing-objects-bugs/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/tests/typing-objects-bugs/_log
+/testsuite/tests/typing-objects-bugs/*.so
+/testsuite/tests/typing-objects-bugs/*.a
+/testsuite/tests/typing-objects-bugs/*.result
+/testsuite/tests/typing-objects-bugs/*.byte
+/testsuite/tests/typing-objects-bugs/*.native
+/testsuite/tests/typing-objects-bugs/program
+/testsuite/tests/typing-objects-bugs/*.cm*
+/testsuite/tests/typing-objects-bugs/*.o
+
+# /testsuite/tests/typing-poly/
+/testsuite/tests/typing-poly/*.o
+/testsuite/tests/typing-poly/*.a
+/testsuite/tests/typing-poly/*.so
+/testsuite/tests/typing-poly/*.obj
+/testsuite/tests/typing-poly/*.cm[ioxa]
+/testsuite/tests/typing-poly/*.cmx[as]
+/testsuite/tests/typing-poly/*.annot
+/testsuite/tests/typing-poly/*.result
+/testsuite/tests/typing-poly/*.byte
+/testsuite/tests/typing-poly/*.native
+/testsuite/tests/typing-poly/program
+/testsuite/tests/typing-poly/.depend
+/testsuite/tests/typing-poly/.depend.nt
+/testsuite/tests/typing-poly/.DS_Store
+
+# /testsuite/tests/typing-poly-bugs/
+/testsuite/tests/typing-poly-bugs/*.o
+/testsuite/tests/typing-poly-bugs/*.a
+/testsuite/tests/typing-poly-bugs/*.so
+/testsuite/tests/typing-poly-bugs/*.obj
+/testsuite/tests/typing-poly-bugs/*.cm[ioxa]
+/testsuite/tests/typing-poly-bugs/*.cmx[as]
+/testsuite/tests/typing-poly-bugs/*.annot
+/testsuite/tests/typing-poly-bugs/*.result
+/testsuite/tests/typing-poly-bugs/*.byte
+/testsuite/tests/typing-poly-bugs/*.native
+/testsuite/tests/typing-poly-bugs/program
+/testsuite/tests/typing-poly-bugs/program.exe
+/testsuite/tests/typing-poly-bugs/.depend
+/testsuite/tests/typing-poly-bugs/.depend.nt
+/testsuite/tests/typing-poly-bugs/.DS_Store
+
+# /testsuite/tests/typing-polyvariants-bugs/
+/testsuite/tests/typing-polyvariants-bugs/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/tests/typing-polyvariants-bugs/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/tests/typing-polyvariants-bugs/_log
+/testsuite/tests/typing-polyvariants-bugs/*.so
+/testsuite/tests/typing-polyvariants-bugs/*.a
+/testsuite/tests/typing-polyvariants-bugs/*.result
+/testsuite/tests/typing-polyvariants-bugs/*.byte
+/testsuite/tests/typing-polyvariants-bugs/*.native
+/testsuite/tests/typing-polyvariants-bugs/program
+/testsuite/tests/typing-polyvariants-bugs/*.cm*
+/testsuite/tests/typing-polyvariants-bugs/*.o
+
+# /testsuite/tests/typing-polyvariants-bugs-2/
+/testsuite/tests/typing-polyvariants-bugs-2/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/tests/typing-polyvariants-bugs-2/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/tests/typing-polyvariants-bugs-2/_log
+/testsuite/tests/typing-polyvariants-bugs-2/*.so
+/testsuite/tests/typing-polyvariants-bugs-2/*.a
+/testsuite/tests/typing-polyvariants-bugs-2/*.result
+/testsuite/tests/typing-polyvariants-bugs-2/*.byte
+/testsuite/tests/typing-polyvariants-bugs-2/*.native
+/testsuite/tests/typing-polyvariants-bugs-2/program
+/testsuite/tests/typing-polyvariants-bugs-2/*.cm*
+/testsuite/tests/typing-polyvariants-bugs-2/*.o
+
+# /testsuite/tests/typing-private/
+/testsuite/tests/typing-private/*.o
+/testsuite/tests/typing-private/*.a
+/testsuite/tests/typing-private/*.so
+/testsuite/tests/typing-private/*.obj
+/testsuite/tests/typing-private/*.cm[ioxa]
+/testsuite/tests/typing-private/*.cmx[as]
+/testsuite/tests/typing-private/*.annot
+/testsuite/tests/typing-private/*.result
+/testsuite/tests/typing-private/*.byte
+/testsuite/tests/typing-private/*.native
+/testsuite/tests/typing-private/program
+/testsuite/tests/typing-private/.depend
+/testsuite/tests/typing-private/.depend.nt
+/testsuite/tests/typing-private/.DS_Store
+
+# /testsuite/tests/typing-private-bugs/
+/testsuite/tests/typing-private-bugs/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/tests/typing-private-bugs/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/tests/typing-private-bugs/_log
+/testsuite/tests/typing-private-bugs/*.so
+/testsuite/tests/typing-private-bugs/*.a
+/testsuite/tests/typing-private-bugs/*.result
+/testsuite/tests/typing-private-bugs/*.byte
+/testsuite/tests/typing-private-bugs/*.native
+/testsuite/tests/typing-private-bugs/program
+/testsuite/tests/typing-private-bugs/*.cm*
+/testsuite/tests/typing-private-bugs/*.o
+
+# /testsuite/tests/typing-recmod/
+/testsuite/tests/typing-recmod/# svn propset -R svn:ignore -F .svnignore .
+/testsuite/tests/typing-recmod/# find . -name .svnignore -print | while read f; do svn propset svn:ignore -F $f `dirname $f`; done
+/testsuite/tests/typing-recmod/_log
+/testsuite/tests/typing-recmod/*.so
+/testsuite/tests/typing-recmod/*.a
+/testsuite/tests/typing-recmod/*.result
+/testsuite/tests/typing-recmod/*.byte
+/testsuite/tests/typing-recmod/*.native
+/testsuite/tests/typing-recmod/program
+/testsuite/tests/typing-recmod/*.cm*
+/testsuite/tests/typing-recmod/*.o
+
+# /testsuite/tests/typing-short-paths/
+/testsuite/tests/typing-short-paths/*.o
+/testsuite/tests/typing-short-paths/*.a
+/testsuite/tests/typing-short-paths/*.so
+/testsuite/tests/typing-short-paths/*.obj
+/testsuite/tests/typing-short-paths/*.cm[ioxat]
+/testsuite/tests/typing-short-paths/*.cmx[as]
+/testsuite/tests/typing-short-paths/*.cmti
+/testsuite/tests/typing-short-paths/*.annot
+/testsuite/tests/typing-short-paths/*.result
+/testsuite/tests/typing-short-paths/*.byte
+/testsuite/tests/typing-short-paths/*.native
+/testsuite/tests/typing-short-paths/program
+/testsuite/tests/typing-short-paths/program.exe
+/testsuite/tests/typing-short-paths/.depend
+/testsuite/tests/typing-short-paths/.depend.nt
+/testsuite/tests/typing-short-paths/.DS_Store
+
+# /testsuite/tests/typing-signatures/
+/testsuite/tests/typing-signatures/*.o
+/testsuite/tests/typing-signatures/*.a
+/testsuite/tests/typing-signatures/*.so
+/testsuite/tests/typing-signatures/*.obj
+/testsuite/tests/typing-signatures/*.cm[ioxa]
+/testsuite/tests/typing-signatures/*.cmx[as]
+/testsuite/tests/typing-signatures/*.annot
+/testsuite/tests/typing-signatures/*.result
+/testsuite/tests/typing-signatures/*.byte
+/testsuite/tests/typing-signatures/*.native
+/testsuite/tests/typing-signatures/program
+/testsuite/tests/typing-signatures/.depend
+/testsuite/tests/typing-signatures/.depend.nt
+/testsuite/tests/typing-signatures/.DS_Store
+
+# /testsuite/tests/typing-sigsubst/
+/testsuite/tests/typing-sigsubst/*.o
+/testsuite/tests/typing-sigsubst/*.a
+/testsuite/tests/typing-sigsubst/*.so
+/testsuite/tests/typing-sigsubst/*.obj
+/testsuite/tests/typing-sigsubst/*.cm[ioxa]
+/testsuite/tests/typing-sigsubst/*.cmx[as]
+/testsuite/tests/typing-sigsubst/*.annot
+/testsuite/tests/typing-sigsubst/*.result
+/testsuite/tests/typing-sigsubst/*.byte
+/testsuite/tests/typing-sigsubst/*.native
+/testsuite/tests/typing-sigsubst/program
+/testsuite/tests/typing-sigsubst/.depend
+/testsuite/tests/typing-sigsubst/.depend.nt
+/testsuite/tests/typing-sigsubst/.DS_Store
+
+# /testsuite/tests/typing-typeparam/
+/testsuite/tests/typing-typeparam/*.o
+/testsuite/tests/typing-typeparam/*.a
+/testsuite/tests/typing-typeparam/*.so
+/testsuite/tests/typing-typeparam/*.obj
+/testsuite/tests/typing-typeparam/*.cm[ioxa]
+/testsuite/tests/typing-typeparam/*.cmx[as]
+/testsuite/tests/typing-typeparam/*.annot
+/testsuite/tests/typing-typeparam/*.result
+/testsuite/tests/typing-typeparam/*.byte
+/testsuite/tests/typing-typeparam/*.native
+/testsuite/tests/typing-typeparam/program
+/testsuite/tests/typing-typeparam/.depend
+/testsuite/tests/typing-typeparam/.depend.nt
+/testsuite/tests/typing-typeparam/.DS_Store
+
+# /testsuite/tests/typing-warnings/
+/testsuite/tests/typing-warnings/*.o
+/testsuite/tests/typing-warnings/*.a
+/testsuite/tests/typing-warnings/*.so
+/testsuite/tests/typing-warnings/*.obj
+/testsuite/tests/typing-warnings/*.cm[ioxat]
+/testsuite/tests/typing-warnings/*.cmx[as]
+/testsuite/tests/typing-warnings/*.cmti
+/testsuite/tests/typing-warnings/*.annot
+/testsuite/tests/typing-warnings/*.result
+/testsuite/tests/typing-warnings/*.byte
+/testsuite/tests/typing-warnings/*.native
+/testsuite/tests/typing-warnings/program
+/testsuite/tests/typing-warnings/program.exe
+/testsuite/tests/typing-warnings/.depend
+/testsuite/tests/typing-warnings/.depend.nt
+/testsuite/tests/typing-warnings/.DS_Store
+
+# /testsuite/tests/utils/
+/testsuite/tests/utils/*.o
+/testsuite/tests/utils/*.a
+/testsuite/tests/utils/*.so
+/testsuite/tests/utils/*.obj
+/testsuite/tests/utils/*.cm[ioxat]
+/testsuite/tests/utils/*.cmx[as]
+/testsuite/tests/utils/*.cmti
+/testsuite/tests/utils/*.annot
+/testsuite/tests/utils/*.result
+/testsuite/tests/utils/*.byte
+/testsuite/tests/utils/*.native
+/testsuite/tests/utils/program
+/testsuite/tests/utils/program.exe
+/testsuite/tests/utils/.depend
+/testsuite/tests/utils/.depend.nt
+/testsuite/tests/utils/.DS_Store
+
+# /testsuite/tests/warnings/
+/testsuite/tests/warnings/*.o
+/testsuite/tests/warnings/*.a
+/testsuite/tests/warnings/*.so
+/testsuite/tests/warnings/*.obj
+/testsuite/tests/warnings/*.lib
+/testsuite/tests/warnings/*.dll
+/testsuite/tests/warnings/*.cm[ioxat]
+/testsuite/tests/warnings/*.cmx[as]
+/testsuite/tests/warnings/*.cmti
+/testsuite/tests/warnings/*.annot
+/testsuite/tests/warnings/*.result
+/testsuite/tests/warnings/*.byte
+/testsuite/tests/warnings/*.native
+/testsuite/tests/warnings/program
+/testsuite/tests/warnings/*.exe
+/testsuite/tests/warnings/*.exe.manifest
+/testsuite/tests/warnings/.depend
+/testsuite/tests/warnings/.depend.nt
+/testsuite/tests/warnings/.DS_Store
+
+# /tools/
+/tools/*.o
+/tools/*.a
+/tools/*.so
+/tools/*.obj
+/tools/*.lib
+/tools/*.dll
+/tools/*.cm[ioxat]
+/tools/*.cmx[as]
+/tools/*.cmti
+/tools/*.annot
+/tools/*.result
+/tools/*.byte
+/tools/*.native
+/tools/program
+/tools/*.exe
+/tools/*.exe.manifest
+/tools/.depend
+/tools/.depend.nt
+/tools/.DS_Store
+/tools/ocamldep
+/tools/ocamldep.opt
+/tools/ocamldep.bak
+/tools/ocamlprof
+/tools/opnames.ml
+/tools/dumpobj
+/tools/dumpapprox
+/tools/objinfo
+/tools/cvt_emit
+/tools/cvt_emit.bak
+/tools/cvt_emit.ml
+/tools/ocamlcp
+/tools/ocamloptp
+/tools/ocamlmktop
+/tools/primreq
+/tools/ocamldumpobj
+/tools/keywords
+/tools/lexer299.ml
+/tools/ocaml299to3
+/tools/ocamlmklib
+/tools/ocamlmklibconfig.ml
+/tools/lexer301.ml
+/tools/scrapelabels
+/tools/addlabels
+/tools/objinfo_helper
+/tools/read_cmt
+/tools/read_cmt.opt
+
+# /toplevel/
+/toplevel/.depend
+/toplevel/configure
+/toplevel/ocamlc
+/toplevel/ocamlc.opt
+/toplevel/expunge
+/toplevel/ocaml
+/toplevel/ocamlopt
+/toplevel/ocamlopt.opt
+/toplevel/ocamlcomp.sh
+/toplevel/ocamlcompopt.sh
+/toplevel/package-macosx
+/toplevel/.DS_Store
+/toplevel/*.annot
+/toplevel/_boot_log1
+/toplevel/_boot_log2
+/toplevel/_build
+/toplevel/_log
+/toplevel/myocamlbuild_config.ml
+/toplevel/ocamlnat
+/toplevel/*.cm*
+/toplevel/*.o
+
+# /typing/
+/typing/*.o
+/typing/*.a
+/typing/*.so
+/typing/*.obj
+/typing/*.dll
+/typing/*.cm[ioxat]
+/typing/*.cmx[as]
+/typing/*.cmti
+/typing/*.annot
+/typing/*.result
+/typing/*.byte
+/typing/*.native
+/typing/program
+/typing/*.exe
+/typing/.depend
+/typing/.depend.nt
+/typing/.DS_Store
+
+# /utils/
+/utils/*.o
+/utils/*.a
+/utils/*.so
+/utils/*.obj
+/utils/*.dll
+/utils/*.cm[ioxat]
+/utils/*.cmx[as]
+/utils/*.cmti
+/utils/*.annot
+/utils/*.result
+/utils/*.byte
+/utils/*.native
+/utils/program
+/utils/*.exe
+/utils/.depend
+/utils/.depend.nt
+/utils/.DS_Store
+/utils/config.ml
+
+# /yacc/
+/yacc/*.o
+/yacc/*.a
+/yacc/*.so
+/yacc/*.obj
+/yacc/*.cm[ioxa]
+/yacc/*.cmx[as]
+/yacc/*.annot
+/yacc/*.result
+/yacc/*.byte
+/yacc/*.native
+/yacc/program
+/yacc/program.exe
+/yacc/.depend
+/yacc/.depend.nt
+/yacc/.DS_Store
+/yacc/ocamlyacc
+/yacc/ocamlyacc.exe
+/yacc/version.h
+/yacc/.gdb_history
diff --git a/.travis-ci.sh b/.travis-ci.sh
new file mode 100644
index 0000000000..bee3ad19bb
--- /dev/null
+++ b/.travis-ci.sh
@@ -0,0 +1,19 @@
+case $XARCH in
+i386)
+ ./configure
+ make world.opt
+ sudo make install
+ cd testsuite && make all
+ git clone git://github.com/ocaml/camlp4
+ cd camlp4 && ./configure && make && sudo make install
+ git clone git://github.com/ocaml/opam
+ cd opam && ./configure && make lib-ext && make && sudo make install
+ opam init -y -a git://github.com/ocaml/opam-repository
+ opam install -y oasis
+ opam pin add -y utop https://github.com/diml/utop
+ ;;
+*)
+ echo unknown arch
+ exit 1
+ ;;
+esac
diff --git a/.travis.yml b/.travis.yml
new file mode 100644
index 0000000000..3015c16d3b
--- /dev/null
+++ b/.travis.yml
@@ -0,0 +1,4 @@
+language: c
+script: bash -ex .travis-ci.sh
+env:
+ - XARCH=i386
diff --git a/Changes b/Changes
index 3a9bc539b6..7c1994c3f8 100644
--- a/Changes
+++ b/Changes
@@ -1,149 +1,299 @@
Next version:
-------------
+Ocaml 4.02.0:
+-------------
+
(Changes that can break existing programs are marked with a "*")
Language features:
- Attributes and extension nodes
-- Generative functors
+ (Alain Frisch)
+- PR#5095: Generative functors
+ (Jacques Garrigue)
- Module aliases
+ (Jacques Garrigue)
+* Alternative syntax for string literals {id|...|id} (can break comments)
+ (Alain Frisch)
+- 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
+ (Jeremy Yallop, backend by Alain Frisch)
+- PR#5584: Extensible open datatypes
+ (Leo White)
Build system for the OCaml distribution:
- Use -bin-annot when building.
+- Use GNU make instead of portable makefiles.
-Camlp4:
-- Removed from the official distribution
-
-Other libraries:
-* Labltk: removed from the distribution, now available as a third-party library
+Shedding weight:
+* Removed Camlp4 from the distribution, now available as third-party software.
+* Removed Labltk from the distribution, now available as a third-party library.
Type system:
-* Keep typing of pattern cases independent in principal mode
+* PR#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)
+ (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
an applicative functor if no types are created
+ (Jacques Garrigue, suggestion by Leo White)
* Module aliases are now typed in a specific way, which remembers their
identity. In particular this changes the signature inferred by
"module type of"
+ (Jacques Garrigue)
- PR#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.
-- PR#6333: Compare first class module types structurally rather than
+ (Jacques Garrigue)
+* PR#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)
Compilers:
-- PR#6269 Optimization of string matching (patch by Benoit Vaugon
- and Luc Maranget)
+- More aggressive constant propagation, including float and
+ int32/int64/nativeint arithmetic. Constant propagation for floats
+ can be turned off with option -no-float-const-prop, for codes that
+ change FP rounding modes at run-time.
+ (Xavier Leroy)
+- New back-end optimization pass: common subexpression elimination (CSE).
+ (Reuses results of previous computations instead of recomputing them.)
+ (Xavier Leroy)
+- 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
+ (Benoît Vaugon and Luc Maranget)
- Experimental native code generator for AArch64 (ARM 64 bits)
-- Optimization of integer division and modulus by constant divisors
- (feature wish PR#6042)
+ (Xavier Leroy)
+- PR#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
+* "-o" now sets module name to the output file name up to the first "."
+ (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 and Mark Shinwell)
+* PR#5779: better sharing of structured constants
+ (Alain Frisch)
- PR#6182: better message for virtual objects and class types
(Leo P. White, Stephen Dolan)
- PR#5817: new flag to keep locations in cmi files
+ (Alain Frisch)
- PR#5854: issue warning 3 when referring to a value marked with
- the [@@deprecated] attribute
-- PR#6203: Constant exception constructor no longer allocate
+ the [@@ocaml.deprecated] attribute
+ (Alain Frisch, suggestion by Pierre-Marie Pédrot)
+* PR#6203: Constant exception constructors no longer allocate
+ (Alain Frisch)
- PR#6311: Improve signature mismatch error messages
+ (Alain Frisch, suggestion by Daniel Bünzli)
- PR#6345: Better compilation of optional arguments with default values
-- PR#6260: Unnecessary boxing in let (patch by vbrankov)
+ (Alain Frisch, review by Jacques Garrigue)
+- PR#6260: Unnecessary boxing in let
+ (Vladimir Brankov)
+- PR#6017: a new format implementation based on GADTs
+ (Benoît Vaugon and Gabriel Scherer)
Toplevel interactive system:
-- Support for directive with multiple arguments
-- PR#5377: New "#show" directive
+- PR#5377: New "#show_*" directives
+ (ygrek, Jacques Garrigue and Alain Frisch)
Runtime system:
+- New configure option "-no-naked-pointers" to improve performance by
+ avoiding page table tests during block darkening and the marking phase
+ of the major GC. In this mode, all out-of-heap pointers must point at
+ things that look like OCaml values: in particular they must have a valid
+ header. The colour of said headers should be black.
+ (Mark Shinwell, reviews by Damien Doligez and Xavier Leroy)
+- Fixed bug in native code version of [caml_raise_with_string] that could
+ potentially lead to heap corruption.
+ (Mark Shinwell)
+- Blocks initialized by [CAMLlocal*] and [caml_alloc] are now filled with
+ [Val_unit] rather than zero.
+ (Mark Shinwell)
- Fixed a major performance problem on large heaps (~1GB) by making heap
- increments proportional to heap size
+ increments proportional to heap size by default
+ (Damien Doligez)
- PR#4765: Structural equality should treat exception specifically
-- PR#5009: Extending exception tag blocks
+ (Alain Frisch)
+- PR#5009: efficient comparison/indexing of exceptions
+ (Alain Frisch, request by Markus Mottl)
- PR#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
64-bit integer arithmetic was removed, the C compiler must support a
64-bit integer type.
+ (Xavier Leroy)
Standard library:
+* Add new modules: Bytes and BytesLabels.
+ (Damien Doligez)
- PR#4986: add List.sort_uniq and Set.of_list
+ (Alain Frisch)
- PR#5935: a faster version of "raise" which does not maintain the backtrace
+ (Alain Frisch)
- PR#6146: support "Unix.kill pid Sys.sigkill" under Windows
-- PR#6148: speed improvement for Buffer (patch by John Whitington)
+ (Romain Bardou and Alain Frisch)
+- PR#6148: speed improvement for Buffer
+ (John Whitington)
- PR#6180: efficient creation of uninitialized float arrays
+ (Alain Frisch, request by Markus Mottl)
OCamldoc:
- PR#6257: handle full doc comments for variant constructors and
- record fields
+ record fields
+ (Maxence Guesdon, request by ygrek)
- PR#6310: fix ocamldoc's subscript/superscript CSS font size
- (patch by Anil Madhavapeddy)
-- PR#6273: fix Sys.file_exists on large files (Win32)
- (patch by Christoph Bauer)
+ (Anil Madhavapeddy)
+- PR#6425: fix generation of man pages
+ (Maxence Guesdon, report by Anil Madhavapeddy)
Bug fixes:
+- PR#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)
+ (Alain Frisch, report by Bart Jacobs)
- PR#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
+ (user 'daweil')
- PR#5598: follow-up fix related to PR#6165
+ (Damien Doligez)
- PR#5820: Fix camlp4 lexer roll back problem
+ (Hongbo Zhang)
+- PR#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 regression bug caused by commit 13047
+ (Hongbo Zhang, report by Christophe Troestler)
- PR#6109: Typos in ocamlbuild error messages
-- PR#6116: more efficient implementation of Digest.to_hex (patch by ygrek)
+ (Gabriel Kerneis)
+- PR#6116: more efficient implementation of Digest.to_hex
+ (ygrek)
+- PR#6142: add cmt file support to ocamlobjinfo
+ (Anil Madhavapeddy)
- PR#6165: Alterations to handling of \013 in source files breaking other tools
-- PR#6173: Typing error message is worse that before
+ (David Allsopp)
+- PR#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)
-- PR#6175: Fix open!
+ (Jacques Garrigue and Grégoire Henry, report by Chantal Keller)
+- PR#6175: add open! support to camlp4
+ (Hongbo Zhang)
- PR#6183: enhanced documentation for 'Unix.shutdown_connection'
+ (Anil Madhavapeddy, report by Jun Furuse)
- PR#6184: ocamlbuild: `ocamlfind ocamldep` does not support -predicate
- (report and patch by Jacques-Pascal Deplaix)
+ (Jacques-Pascal Deplaix)
- PR#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
+ exceptions and multiple bindings of the form "let x = a let y = b;;".
+ (Xavier Leroy)
- PR#6216: inlining of GADT matches generates invalid assembly
+ (Xavier Leroy and Alain Frisch, report by Mark Shinwell)
- PR#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
+ (Jacques Garrigue, report by Hongbo Zhang)
- PR#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
+ (Jacques Garrigue, report by Leo White)
- PR#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
+ (Xavier Leroy, report by Pierre-Marie Pédrot)
- PR#6262: equality of first-class modules take module aliases into account
+ (Alain Frisch and Leo White)
- PR#6267: more information printed by "bt" command of ocamldebug
+ (Josh Watzman)
+- PR#6268: -DMODEL_$(MODEL) not passed when building asmrun/arm.p.o
+ (Peter Michael Green)
+- PR#6273: fix Sys.file_exists on large files (Win32)
+ (Christoph Bauer)
- PR#6275: Soundness bug related to type constraints
+ (Jacques Garrigue, report by Leo White)
- PR#6293: Assert_failure with invalid package type
+ (Jacques Garrigue, report by Elnatan Reisner)
+- PR#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
+ (Jacques Garrigue, report by Alain Frisch)
- PR#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
+ (Leo White and Jacques Garrigue, report by Jeremy Yallop)
- PR#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
+ (Xavier Leroy, report by Leo White)
+- PR#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
+ (Leo White)
+- PR#6385: wrong allocation of large closures by the bytecode interpreter
+ (Xavier Leroy, report by Stephen Dolan)
+- PR#6394: Assertion failed in Typecore.expand_path
+ (Alain Frisch and Jacques Garrigue)
+- PR#6405: unsound interaction of -rectypes and GADTs
+ (Jacques Garrigue, report by Gabriel Scherer and Benoît Vaugon)
+- PR#6418: reimplement parametrized Format tags/indentation with GADTs
+ (Benoît Vaugon)
+- PR#6460: runtime assertion failure with large [| e1;...eN |]
+ float array expressions
+ (Leo White)
+- PR#6482: ocamlbuild fails when _tags file in unhygienic directory
+ (Gabriel Scherer)
+- PR#6509: add -linkall flag to ocamlcommon.cma
+ (Frédéric Bour)
- fix -dsource printing of "external _pipe = ..."
(Gabriel Scherer)
- bound-checking bug in caml_string_{get,set}{16,32,64}
(Pierre Chambart and Gabriel Scherer, report by Nicolas Trangez)
- sometimes wrong stack alignment at out-of-bounds array access
- (Gabriel Scherer, review by Xavier Leroy, report by Pierre Chambart)
+ (Gabriel Scherer and Xavier Leroy, report by Pierre Chambart)
Features wishes:
- PR#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
- hexa representations (patch by Zoe Paraskevopoulou)
-- PR#5547: Enable the "-use-ocamlfind" option by default
+ hex representations
+ (Zoe Paraskevopoulou, review by Gabriel Scherer)
- PR#5650: Camlp4FoldGenerator doesn't handle well "abstract" types
-- PR#5808: allow simple patterns, not only identifiers, in "let p : t = ..."
-- PR#6000: add a warning for non-principal coercions to format
+ (Hongbo Zhang)
+- PR#5808: allow simple patterns, not just identifiers, in "let p : t = ..."
+ (Alain Frisch)
+- PR#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
+ (Jacques Garrigue, report by Damien Doligez)
- PR#6054: add support for M.[ foo ], M.[| foo |] etc.
- (patch by Kaustuv Chaudhuri)
+ (Kaustuv Chaudhuri)
- PR#6064: GADT representation for Bigarray.kind + CAML_BA_CHAR runtime kind
-- PR#6071: Add a -noinit option to the toplevel (patch by David Sheets)
+ (Jeremy Yallop, review by Gabriel Scherer)
+- PR#6071: Add a -noinit option to the toplevel
+ (David Sheets)
- PR#6166: document -ocamldoc option of ocamlbuild
+ (Xavier Clerc)
- PR#6187: ocamlbuild: warn when using -plugin-tag(s) without myocamlbuild.ml
- (patch by Jacques-Pascal Deplaix)
+ (Jacques-Pascal Deplaix)
- PR#6246: allow wilcard _ as for-loop index
+ (Alain Frisch, request by ygrek)
- PR#6270: remove need for -I directives to ocamldebug in common case
- (patch by Josh Watzman, review by Xavier Clerc and Alain Frisch)
+ (Josh Watzman, review by Xavier Clerc and Alain Frisch)
- PR#6358: obey DESTDIR in install targets
- (Gabriel Scherer)
+ (Gabriel Scherer, request by François Berenger)
+- PR#6406: Expose OCaml version in C headers
+ (Peter Zotov and Romain Calascibetta)
- ocamllex: user-definable refill action
- (patch by Frédéric Bour, review by Gabriel Scherer and Luc Maranget)
+ (Frédéric Bour, review by Gabriel Scherer and Luc Maranget)
- shorten syntax for functor signatures: "functor (M1:S1) (M2:S2) .. -> .."
- (patches by Thomas Gazagnaire and Jeremy Yallop, review by Gabriel Scherer)
+ (Thomas Gazagnaire and Jeremy Yallop, review by Gabriel Scherer)
OCaml 4.01.0:
@@ -301,7 +451,7 @@ Bug fixes:
(Alain Frisch)
- PR#5552: unrecognized gcc option -no-cpp-precomp
(Damien Doligez, report by Markus Mottl)
-- PR#5580: missed opportunities for constant propagation
+* PR#5580: missed opportunities for constant propagation
(Xavier Leroy and John Carr)
- PR#5611: avoid clashes betwen .cmo files and output files during linking
(Wojciech Meyer)
@@ -498,8 +648,6 @@ Bug fixes:
(Jacques Garrigue, report by Elnatan Reisner)
- PR#6058: 'ocamlbuild -use-ocamlfind -tag thread -package threads t.cma' fails
(Gabriel Scherer, report by Hezekiah M. Carty)
-- PR#6060: ocamlbuild rules for -principal, -strict-sequence and -short-paths
- (Anil Madhavapeddy)
- PR#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
@@ -565,6 +713,12 @@ Feature wishes:
(Anil Madhavapeddy, review by Benedikt Meurer)
- PR#6059: add -output-obj rules for ocamlbuild
(Anil Madhavapeddy)
+- PR#6060: ocamlbuild tags 'principal', 'strict_sequence' and 'short_paths'
+ (Anil Madhavapeddy)
+- PR#6495: ocamlbuild tags 'safe_string', 'unsafe_string'
+ (Anil Madhavapeddy)
+- ocamlbuild tag 'no_alias_deps'
+ (Daniel Bünzli)
Tools:
- OCamlbuild now features a bin_annot tag to generate .cmt files.
diff --git a/INSTALL b/INSTALL
index c703d2ef78..63ae5c67bf 100644
--- a/INSTALL
+++ b/INSTALL
@@ -153,8 +153,9 @@ Examples:
to build a 64-bit version of OCaml:
./configure -cc "gcc -m64"
- On a MacOSX 10.6/Intel Core 2, to build a 32-bit version of OCaml:
- ./configure -cc "gcc -m32" -as "as -arch i386" -aspp "gcc -m32 -c"
+ On Intel Mac OS X, 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"
diff --git a/Makefile b/Makefile
index ccddd149aa..733ed99d47 100644
--- a/Makefile
+++ b/Makefile
@@ -17,7 +17,8 @@ include stdlib/StdlibModules
CAMLC=boot/ocamlrun boot/ocamlc -nostdlib -I boot
CAMLOPT=boot/ocamlrun ./ocamlopt -nostdlib -I stdlib -I otherlibs/dynlink
-COMPFLAGS=-strict-sequence -w +33..39+48 -warn-error A -bin-annot $(INCLUDES)
+COMPFLAGS=-strict-sequence -w +33..39+48 -warn-error A -bin-annot \
+ -safe-string $(INCLUDES)
LINKFLAGS=
CAMLYACC=boot/ocamlyacc
@@ -84,10 +85,13 @@ ASMCOMP=asmcomp/arch.cmo asmcomp/debuginfo.cmo \
asmcomp/clambda.cmo asmcomp/printclambda.cmo asmcomp/compilenv.cmo \
asmcomp/closure.cmo asmcomp/strmatch.cmo asmcomp/cmmgen.cmo \
asmcomp/printmach.cmo asmcomp/selectgen.cmo asmcomp/selection.cmo \
- asmcomp/comballoc.cmo asmcomp/liveness.cmo \
+ asmcomp/comballoc.cmo \
+ asmcomp/CSEgen.cmo asmcomp/CSE.cmo \
+ asmcomp/liveness.cmo \
asmcomp/spill.cmo asmcomp/split.cmo \
asmcomp/interf.cmo asmcomp/coloring.cmo \
asmcomp/reloadgen.cmo asmcomp/reload.cmo \
+ asmcomp/deadcode.cmo \
asmcomp/printlinear.cmo asmcomp/linearize.cmo \
asmcomp/schedgen.cmo asmcomp/scheduling.cmo \
asmcomp/emitaux.cmo asmcomp/emit.cmo asmcomp/asmgen.cmo \
@@ -121,11 +125,7 @@ defaultentry:
# Recompile the system using the bootstrap compiler
all:
$(MAKE) runtime
- $(MAKE) ocamlc
- $(MAKE) ocamllex
- $(MAKE) ocamlyacc
- $(MAKE) ocamltools
- $(MAKE) library
+ $(MAKE) coreall
$(MAKE) ocaml
$(MAKE) otherlibraries $(OCAMLBUILDBYTE) $(WITH_DEBUGGER) \
$(WITH_OCAMLDOC)
@@ -145,11 +145,10 @@ world.opt:
#
# make coreboot [old system -- you were in a stable state]
# <change the source>
-# make core [cross-compiler]
-# make partialclean [if you get "inconsistent assumptions"]
+# make clean runtime coreall
# <debug your changes>
-# make core [cross-compiler]
-# make coreboot [new system -- now you are in a stable state]
+# make clean runtime coreall
+# make coreboot [new system -- now in a stable state]
# Core bootstrapping cycle
coreboot:
@@ -198,8 +197,7 @@ coldstart:
# Build the core system: the minimum needed to make depend and bootstrap
core:
$(MAKE) coldstart
- $(MAKE) ocamlc
- $(MAKE) ocamllex ocamlyacc ocamltools library
+ $(MAKE) coreall
# Recompile the core system using the bootstrap compiler
coreall:
@@ -374,7 +372,7 @@ clean:: partialclean
# Shared parts of the system
compilerlibs/ocamlcommon.cma: $(COMMON)
- $(CAMLC) -a -o $@ $(COMMON)
+ $(CAMLC) -a -linkall -o $@ $(COMMON)
partialclean::
rm -f compilerlibs/ocamlcommon.cma
@@ -464,7 +462,6 @@ utils/config.ml: utils/config.mlp config/Makefile
-e 's|%%HOST%%|$(HOST)|' \
-e 's|%%TARGET%%|$(TARGET)|' \
utils/config.mlp > utils/config.ml
- @chmod -w utils/config.ml
partialclean::
rm -f utils/config.ml
@@ -494,7 +491,7 @@ beforedepend:: parsing/lexer.ml
# Shared parts of the system compiled with the native-code compiler
compilerlibs/ocamlcommon.cmxa: $(COMMON:.cmo=.cmx)
- $(CAMLOPT) -a -o $@ $(COMMON:.cmo=.cmx)
+ $(CAMLOPT) -a -linkall -o $@ $(COMMON:.cmo=.cmx)
partialclean::
rm -f compilerlibs/ocamlcommon.cmxa compilerlibs/ocamlcommon.a
@@ -588,6 +585,14 @@ partialclean::
beforedepend:: asmcomp/selection.ml
+asmcomp/CSE.ml: asmcomp/$(ARCH)/CSE.ml
+ ln -s $(ARCH)/CSE.ml asmcomp/CSE.ml
+
+partialclean::
+ rm -f asmcomp/CSE.ml
+
+beforedepend:: asmcomp/CSE.ml
+
asmcomp/reload.ml: asmcomp/$(ARCH)/reload.ml
ln -s $(ARCH)/reload.ml asmcomp/reload.ml
@@ -839,7 +844,7 @@ distclean:
rm -f boot/ocamlrun boot/ocamlrun.exe boot/camlheader boot/ocamlyacc \
boot/*.cm* boot/libcamlrun.a
rm -f config/Makefile config/m.h config/s.h
- rm -f tools/*.bak tools/ocamlmklibconfig.ml
+ rm -f tools/*.bak
rm -f ocaml ocamlc
rm -f testsuite/_log
diff --git a/Makefile.nt b/Makefile.nt
index cfeaac4b52..648c918df1 100644
--- a/Makefile.nt
+++ b/Makefile.nt
@@ -81,10 +81,13 @@ ASMCOMP=asmcomp/arch.cmo asmcomp/debuginfo.cmo \
asmcomp/clambda.cmo asmcomp/printclambda.cmo asmcomp/compilenv.cmo \
asmcomp/closure.cmo asmcomp/strmatch.cmo asmcomp/cmmgen.cmo \
asmcomp/printmach.cmo asmcomp/selectgen.cmo asmcomp/selection.cmo \
- asmcomp/comballoc.cmo asmcomp/liveness.cmo \
+ asmcomp/comballoc.cmo \
+ asmcomp/CSEgen.cmo asmcomp/CSE.cmo \
+ asmcomp/liveness.cmo \
asmcomp/spill.cmo asmcomp/split.cmo \
asmcomp/interf.cmo asmcomp/coloring.cmo \
asmcomp/reloadgen.cmo asmcomp/reload.cmo \
+ asmcomp/deadcode.cmo \
asmcomp/printlinear.cmo asmcomp/linearize.cmo \
asmcomp/schedgen.cmo asmcomp/scheduling.cmo \
asmcomp/emitaux.cmo asmcomp/emit.cmo asmcomp/asmgen.cmo \
@@ -389,7 +392,6 @@ utils/config.ml: utils/config.mlp config/Makefile
-e 's|%%HOST%%|$(HOST)|' \
-e 's|%%TARGET%%|$(TARGET)|' \
utils/config.mlp > utils/config.ml
- @chmod -w utils/config.ml
partialclean::
rm -f utils/config.ml
@@ -519,6 +521,14 @@ partialclean::
beforedepend:: asmcomp/selection.ml
+asmcomp/CSE.ml: asmcomp/$(ARCH)/CSE.ml
+ cp asmcomp/$(ARCH)/CSE.ml asmcomp/CSE.ml
+
+partialclean::
+ rm -f asmcomp/CSE.ml
+
+beforedepend:: asmcomp/CSE.ml
+
asmcomp/reload.ml: asmcomp/$(ARCH)/reload.ml
cp asmcomp/$(ARCH)/reload.ml asmcomp/reload.ml
@@ -716,7 +726,13 @@ depend: beforedepend
alldepend:: depend
distclean:
- ./build/distclean.sh
+ $(MAKE) clean
+ rm -f boot/ocamlrun boot/ocamlrun.exe boot/camlheader boot/ocamlyacc \
+ boot/*.cm* boot/libcamlrun.a
+ rm -f config/Makefile config/m.h config/s.h
+ rm -f tools/*.bak
+ rm -f ocaml ocamlc
+ rm -f testsuite/_log
.PHONY: all backup bootstrap checkstack clean
.PHONY: partialclean beforedepend alldepend cleanboot coldstart
diff --git a/VERSION b/VERSION
index 7bcd56547a..005c112283 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-4.02.0+dev4-2014-04-03
+4.03.0+dev1-2014-07-21
# The version string is the first line of this file.
# It must be in the format described in stdlib/sys.mli
diff --git a/asmcomp/.ignore b/asmcomp/.ignore
index 31d00178a0..8c24e74ad1 100644
--- a/asmcomp/.ignore
+++ b/asmcomp/.ignore
@@ -4,3 +4,4 @@ proc.ml
selection.ml
reload.ml
scheduling.ml
+CSE.ml
diff --git a/asmcomp/CSEgen.ml b/asmcomp/CSEgen.ml
new file mode 100644
index 0000000000..8cd23b0a9b
--- /dev/null
+++ b/asmcomp/CSEgen.ml
@@ -0,0 +1,322 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* Common subexpression elimination by value numbering over extended
+ basic blocks. *)
+
+open Mach
+
+type valnum = int
+
+(* We maintain sets of equations of the form
+ valnums = operation(valnums)
+ plus a mapping from registers to valnums (value numbers). *)
+
+type rhs = operation * valnum array
+
+module Equations =
+ Map.Make(struct type t = rhs let compare = Pervasives.compare end)
+
+type numbering =
+ { num_next: int; (* next fresh value number *)
+ num_eqs: valnum array Equations.t; (* mapping rhs -> valnums *)
+ num_reg: valnum Reg.Map.t } (* mapping register -> valnum *)
+
+let empty_numbering =
+ { num_next = 0; num_eqs = Equations.empty; num_reg = Reg.Map.empty }
+
+(** Generate a fresh value number [v] and associate it to register [r].
+ Returns a pair [(n',v)] with the updated value numbering [n']. *)
+
+let fresh_valnum_reg n r =
+ let v = n.num_next in
+ ({n with num_next = v + 1; num_reg = Reg.Map.add r v n.num_reg}, v)
+
+(* Same, for a set of registers [rs]. *)
+
+let array_fold_transf (f: numbering -> 'a -> numbering * 'b) n (a: 'a array)
+ : numbering * 'b array =
+ match Array.length a with
+ | 0 -> (n, [||])
+ | 1 -> let (n', b) = f n a.(0) in (n', [|b|])
+ | l -> let b = Array.make l 0 and n = ref n in
+ for i = 0 to l - 1 do
+ let (n', x) = f !n a.(i) in
+ b.(i) <- x; n := n'
+ done;
+ (!n, b)
+
+let fresh_valnum_regs n rs =
+ array_fold_transf fresh_valnum_reg n rs
+
+(** [valnum_reg n r] returns the value number for the contents of
+ register [r]. If none exists, a fresh value number is returned
+ and associated with register [r]. The possibly updated numbering
+ is also returned. [valnum_regs] is similar, but for an array of
+ registers. *)
+
+let valnum_reg n r =
+ try
+ (n, Reg.Map.find r n.num_reg)
+ with Not_found ->
+ fresh_valnum_reg n r
+
+let valnum_regs n rs =
+ array_fold_transf valnum_reg n rs
+
+(* Look up the set of equations for an equation with the given rhs.
+ Return [Some res] if there is one, where [res] is the lhs. *)
+
+let find_equation n rhs =
+ try
+ Some(Equations.find rhs n.num_eqs)
+ with Not_found ->
+ None
+
+(* Find a register containing the given value number. *)
+
+let find_reg_containing n v =
+ Reg.Map.fold (fun r v' res -> if v' = v then Some r else res)
+ n.num_reg None
+
+(* Find a set of registers containing the given value numbers. *)
+
+let find_regs_containing n vs =
+ match Array.length vs with
+ | 0 -> Some [||]
+ | 1 -> begin match find_reg_containing n vs.(0) with
+ | None -> None
+ | Some r -> Some [|r|]
+ end
+ | l -> let rs = Array.make l Reg.dummy in
+ begin try
+ for i = 0 to l - 1 do
+ match find_reg_containing n vs.(i) with
+ | None -> raise Exit
+ | Some r -> rs.(i) <- r
+ done;
+ Some rs
+ with Exit ->
+ None
+ end
+
+(* Associate the given value number to the given result register,
+ without adding new equations. *)
+
+let set_known_reg n r v =
+ { n with num_reg = Reg.Map.add r v n.num_reg }
+
+(* Associate the given value numbers to the given result registers,
+ without adding new equations. *)
+
+let array_fold2 f n a1 a2 =
+ let l = Array.length a1 in
+ assert (l = Array.length a2);
+ let n = ref n in
+ for i = 0 to l - 1 do n := f !n a1.(i) a2.(i) done;
+ !n
+
+let set_known_regs n rs vs =
+ array_fold2 set_known_reg n rs vs
+
+(* Record the effect of a move: no new equations, but the result reg
+ maps to the same value number as the argument reg. *)
+
+let set_move n src dst =
+ let (n1, v) = valnum_reg n src in
+ { n1 with num_reg = Reg.Map.add dst v n1.num_reg }
+
+(* Record the equation [fresh valnums = rhs] and associate the given
+ result registers [rs] to [fresh valnums]. *)
+
+let set_fresh_regs n rs rhs =
+ let (n1, vs) = fresh_valnum_regs n rs in
+ { n1 with num_eqs = Equations.add rhs vs n.num_eqs }
+
+(* Forget everything we know about the given result registers,
+ which are receiving unpredictable values at run-time. *)
+
+let set_unknown_regs n rs =
+ { n with num_reg = Array.fold_right Reg.Map.remove rs n.num_reg }
+
+(* Keep only the equations satisfying the given predicate. *)
+
+let filter_equations pred n =
+ { n with num_eqs = Equations.filter (fun (op,_) res -> pred op) n.num_eqs }
+
+(* Prepend a set of moves before [i] to assign [srcs] to [dsts]. *)
+
+let insert_single_move i src dst = instr_cons (Iop Imove) [|src|] [|dst|] i
+
+let insert_move srcs dsts i =
+ match Array.length srcs with
+ | 0 -> i
+ | 1 -> instr_cons (Iop Imove) srcs dsts i
+ | l -> (* Parallel move: first copy srcs into tmps one by one,
+ then copy tmps into dsts one by one *)
+ let tmps = Reg.createv_like srcs in
+ array_fold2 insert_single_move
+ (array_fold2 insert_single_move i srcs tmps) tmps dsts
+
+(* Classification of operations *)
+
+type op_class =
+ | Op_pure (* pure arithmetic, produce one or several result *)
+ | Op_checkbound (* checkbound-style: no result, can raise an exn *)
+ | Op_load (* memory load *)
+ | Op_store of bool (* memory store, false = init, true = assign *)
+ | Op_other (* anything else that does not allocate nor store in memory *)
+
+class cse_generic = object (self)
+
+(* Default classification of operations. Can be overriden in
+ processor-specific files to classify specific operations better. *)
+
+method class_of_operation op =
+ match op with
+ | Imove | Ispill | Ireload -> assert false (* treated specially *)
+ | Iconst_int _ | Iconst_float _ | Iconst_symbol _
+ | Iconst_blockheader _ -> Op_pure
+ | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+ | Iextcall _ -> assert false (* treated specially *)
+ | Istackoffset _ -> Op_other
+ | Iload(_,_) -> Op_load
+ | Istore(_,_,asg) -> Op_store asg
+ | Ialloc _ -> assert false (* treated specially *)
+ | Iintop(Icheckbound) -> Op_checkbound
+ | Iintop _ -> Op_pure
+ | Iintop_imm(Icheckbound, _) -> Op_checkbound
+ | Iintop_imm(_, _) -> Op_pure
+ | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
+ | Ifloatofint | Iintoffloat -> Op_pure
+ | Ispecific _ -> Op_other
+
+(* Operations that are so cheap that it isn't worth factoring them. *)
+
+method is_cheap_operation op =
+ match op with
+ | Iconst_int _ | Iconst_blockheader _ -> true
+ | _ -> false
+
+(* Forget all equations involving memory loads. Performed after a
+ non-initializing store *)
+
+method private kill_loads n =
+ filter_equations (fun o -> self#class_of_operation o <> Op_load) n
+
+(* Perform CSE on the given instruction [i] and its successors.
+ [n] is the value numbering current at the beginning of [i]. *)
+
+method private cse n i =
+ match i.desc with
+ | Iend | Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _)
+ | Iexit _ | Iraise _ ->
+ i
+ | Iop (Imove | Ispill | Ireload) ->
+ (* For moves, we associate the same value number to the result reg
+ as to the argument reg. *)
+ let n1 = set_move n i.arg.(0) i.res.(0) in
+ {i with next = self#cse n1 i.next}
+ | Iop (Icall_ind | Icall_imm _ | Iextcall _) ->
+ (* For function calls, we should at least forget:
+ - equations involving memory loads, since the callee can
+ perform arbitrary memory stores;
+ - equations involving arithmetic operations that can
+ produce bad pointers into the heap (see below for Ialloc);
+ - mappings from hardware registers to value numbers,
+ since the callee does not preserve these registers.
+ That doesn't leave much usable information: checkbounds
+ could be kept, but won't be usable for CSE as one of their
+ arguments is always a memory load. For simplicity, we
+ just forget everything. *)
+ {i with next = self#cse empty_numbering i.next}
+ | Iop (Ialloc _) ->
+ (* For allocations, we must avoid extending the live range of a
+ pseudoregister across the allocation if this pseudoreg can
+ contain a value that looks like a pointer into the heap but
+ is not a pointer to the beginning of a Caml object. PR#6484
+ is an example of such a value (a derived pointer into a
+ block). In the absence of more precise typing information,
+ we just forget everything. *)
+ {i with next = self#cse empty_numbering i.next}
+ | Iop op ->
+ begin match self#class_of_operation op with
+ | Op_pure | Op_checkbound | Op_load ->
+ let (n1, varg) = valnum_regs n i.arg in
+ let n2 = set_unknown_regs n1 (Proc.destroyed_at_oper i.desc) in
+ begin match find_equation n1 (op, varg) with
+ | Some vres ->
+ (* This operation was computed earlier. *)
+ (* Are there registers that hold the results computed earlier? *)
+ begin match find_regs_containing n1 vres with
+ | Some res when (not (self#is_cheap_operation op))
+ && (not (Proc.regs_are_volatile res)) ->
+ (* We can replace res <- op args with r <- move res,
+ provided res are stable (non-volatile) registers.
+ If the operation is very cheap to compute, e.g.
+ an integer constant, don't bother. *)
+ let n3 = set_known_regs n1 i.res vres in
+ (* This is n1 above and not n2 because the move
+ does not destroy any regs *)
+ insert_move res i.res (self#cse n3 i.next)
+ | _ ->
+ (* We already computed the operation but lost its
+ results. Associate the result registers to
+ the result valnums of the previous operation. *)
+ let n3 = set_known_regs n2 i.res vres in
+ {i with next = self#cse n3 i.next}
+ end
+ | None ->
+ (* This operation produces a result we haven't seen earlier. *)
+ let n3 = set_fresh_regs n2 i.res (op, varg) in
+ {i with next = self#cse n3 i.next}
+ end
+ | Op_store false | Op_other ->
+ (* An initializing store or an "other" operation do not invalidate
+ any equations, but we do not know anything about the results. *)
+ let n1 = set_unknown_regs n (Proc.destroyed_at_oper i.desc) in
+ let n2 = set_unknown_regs n1 i.res in
+ {i with next = self#cse n2 i.next}
+ | Op_store true ->
+ (* A non-initializing store can invalidate
+ anything we know about prior loads. *)
+ let n1 = set_unknown_regs n (Proc.destroyed_at_oper i.desc) in
+ let n2 = set_unknown_regs n1 i.res in
+ let n3 = self#kill_loads n2 in
+ {i with next = self#cse n3 i.next}
+ end
+ (* For control structures, we set the numbering to empty at every
+ join point, but propagate the current numbering across fork points. *)
+ | Iifthenelse(test, ifso, ifnot) ->
+ let n1 = set_unknown_regs n (Proc.destroyed_at_oper i.desc) in
+ {i with desc = Iifthenelse(test, self#cse n1 ifso, self#cse n1 ifnot);
+ next = self#cse empty_numbering i.next}
+ | Iswitch(index, cases) ->
+ let n1 = set_unknown_regs n (Proc.destroyed_at_oper i.desc) in
+ {i with desc = Iswitch(index, Array.map (self#cse n1) cases);
+ next = self#cse empty_numbering i.next}
+ | Iloop(body) ->
+ {i with desc = Iloop(self#cse empty_numbering body);
+ next = self#cse empty_numbering i.next}
+ | Icatch(nfail, body, handler) ->
+ {i with desc = Icatch(nfail, self#cse n body,
+ self#cse empty_numbering handler);
+ next = self#cse empty_numbering i.next}
+ | Itrywith(body, handler) ->
+ {i with desc = Itrywith(self#cse n body,
+ self#cse empty_numbering handler);
+ next = self#cse empty_numbering i.next}
+
+method fundecl f =
+ {f with fun_body = self#cse empty_numbering f.fun_body}
+
+end
diff --git a/asmcomp/CSEgen.mli b/asmcomp/CSEgen.mli
new file mode 100644
index 0000000000..ffea33891c
--- /dev/null
+++ b/asmcomp/CSEgen.mli
@@ -0,0 +1,38 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* Common subexpression elimination by value numbering over extended
+ basic blocks. *)
+
+type op_class =
+ | Op_pure (* pure, produce one result *)
+ | Op_checkbound (* checkbound-style: no result, can raise an exn *)
+ | Op_load (* memory load *)
+ | Op_store of bool (* memory store, false = init, true = assign *)
+ | 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
+ operations. *)
+
+ method class_of_operation: Mach.operation -> op_class
+
+ method is_cheap_operation: Mach.operation -> bool
+ (* Operations that are so cheap that it isn't worth factoring them. *)
+
+ (* The following method is the entry point and should not be overridden *)
+ method fundecl: Mach.fundecl -> Mach.fundecl
+
+end
+
+
+
diff --git a/asmcomp/amd64/CSE.ml b/asmcomp/amd64/CSE.ml
new file mode 100644
index 0000000000..6c9b76e822
--- /dev/null
+++ b/asmcomp/amd64/CSE.ml
@@ -0,0 +1,39 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* CSE for the AMD64 *)
+
+open Arch
+open Mach
+open CSEgen
+
+class cse = object (self)
+
+inherit cse_generic as super
+
+method! class_of_operation op =
+ match op with
+ | Ispecific spec ->
+ begin match spec with
+ | Ilea _ -> Op_pure
+ | Istore_int(_, _, is_asg) | Istore_symbol(_, _, is_asg) -> Op_store is_asg
+ | Ioffset_loc(_, _) -> Op_store true
+ | Ifloatarithmem _ | Ifloatsqrtf _ -> Op_load
+ | Ibswap _ | Isqrtf -> super#class_of_operation op
+ end
+ | _ -> super#class_of_operation op
+
+end
+
+let fundecl f =
+ (new cse)#fundecl f
+
diff --git a/asmcomp/amd64/arch.ml b/asmcomp/amd64/arch.ml
index b0a5ffb8b7..3741dd74bc 100644
--- a/asmcomp/amd64/arch.ml
+++ b/asmcomp/amd64/arch.ml
@@ -33,8 +33,8 @@ type addressing_mode =
type specific_operation =
Ilea of addressing_mode (* "lea" gives scaled adds *)
- | Istore_int of nativeint * addressing_mode (* Store an integer constant *)
- | Istore_symbol of string * addressing_mode (* Store a symbol *)
+ | Istore_int of nativeint * addressing_mode * bool (* Store an integer constant *)
+ | Istore_symbol of string * addressing_mode * bool (* Store a symbol *)
| Ioffset_loc of int * addressing_mode (* Add a constant to a location *)
| Ifloatarithmem of float_operation * addressing_mode
(* Float arith operation with memory *)
@@ -101,10 +101,14 @@ let print_addressing printreg addr ppf arg =
let print_specific_operation printreg op ppf arg =
match op with
| Ilea addr -> print_addressing printreg addr ppf arg
- | Istore_int(n, addr) ->
- fprintf ppf "[%a] := %nd" (print_addressing printreg addr) arg n
- | Istore_symbol(lbl, addr) ->
- fprintf ppf "[%a] := \"%s\"" (print_addressing printreg addr) arg lbl
+ | Istore_int(n, addr, is_assign) ->
+ fprintf ppf "[%a] := %nd %s"
+ (print_addressing printreg addr) arg n
+ (if is_assign then "(assign)" else "(init)")
+ | Istore_symbol(lbl, addr, is_assign) ->
+ fprintf ppf "[%a] := \"%s\" %s"
+ (print_addressing printreg addr) arg lbl
+ (if is_assign then "(assign)" else "(init)")
| Ioffset_loc(n, addr) ->
fprintf ppf "[%a] +:= %i" (print_addressing printreg addr) arg n
| Isqrtf ->
diff --git a/asmcomp/amd64/emit.mlp b/asmcomp/amd64/emit.mlp
index bdcc3a18d3..b576ece983 100644
--- a/asmcomp/amd64/emit.mlp
+++ b/asmcomp/amd64/emit.mlp
@@ -335,15 +335,16 @@ let output_epilogue f =
(* Floating-point constants *)
-let float_constants = ref ([] : (string * int) list)
+let float_constants = ref ([] : (int64 * int) list)
let add_float_constant cst =
+ let repr = Int64.bits_of_float cst in
try
- List.assoc cst !float_constants
+ List.assoc repr !float_constants
with
Not_found ->
let lbl = new_label() in
- float_constants := (cst, lbl) :: !float_constants;
+ float_constants := (repr, lbl) :: !float_constants;
lbl
let emit_float_constant (cst, lbl) =
@@ -382,12 +383,12 @@ let emit_instr fallthrough i =
` movq ${emit_nativeint n}, {emit_reg i.res.(0)}\n`
else
` movabsq ${emit_nativeint n}, {emit_reg i.res.(0)}\n`
- | Lop(Iconst_float s) ->
- begin match Int64.bits_of_float (float_of_string s) with
+ | Lop(Iconst_float f) ->
+ begin match Int64.bits_of_float f with
| 0x0000_0000_0000_0000L -> (* +0.0 *)
` xorpd {emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
| _ ->
- let lbl = add_float_constant s in
+ let lbl = add_float_constant f in
` movsd {emit_label lbl}(%rip), {emit_reg i.res.(0)}\n`
end
| Lop(Iconst_symbol s) ->
@@ -448,7 +449,7 @@ let emit_instr fallthrough i =
| Double | Double_u ->
` movsd {emit_addressing addr i.arg 0}, {emit_reg dest}\n`
end
- | Lop(Istore(chunk, addr)) ->
+ | Lop(Istore(chunk, addr, _)) ->
begin match chunk with
| Word ->
` movq {emit_reg i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
@@ -541,9 +542,9 @@ let emit_instr fallthrough i =
` cvttsd2siq {emit_reg i.arg.(0)}, {emit_reg i.res.(0)}\n`
| Lop(Ispecific(Ilea addr)) ->
` leaq {emit_addressing addr i.arg 0}, {emit_reg i.res.(0)}\n`
- | Lop(Ispecific(Istore_int(n, addr))) ->
+ | Lop(Ispecific(Istore_int(n, addr, _))) ->
` movq ${emit_nativeint n}, {emit_addressing addr i.arg 0}\n`
- | Lop(Ispecific(Istore_symbol(s, addr))) ->
+ | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
assert (not !pic_code && not !Clflags.dlcode);
` movq ${emit_symbol s}, {emit_addressing addr i.arg 0}\n`
| Lop(Ispecific(Ioffset_loc(n, addr))) ->
@@ -764,9 +765,9 @@ let emit_item = function
| Cint n ->
` .quad {emit_nativeint n}\n`
| Csingle f ->
- emit_float32_directive ".long" f
+ emit_float32_directive ".long" (Int32.bits_of_float f)
| Cdouble f ->
- emit_float64_directive ".quad" f
+ emit_float64_directive ".quad" (Int64.bits_of_float f)
| Csymbol_address s ->
` .quad {emit_symbol s}\n`
| Clabel_address lbl ->
diff --git a/asmcomp/amd64/emit_nt.mlp b/asmcomp/amd64/emit_nt.mlp
index 77156b8f01..f14e69cd38 100644
--- a/asmcomp/amd64/emit_nt.mlp
+++ b/asmcomp/amd64/emit_nt.mlp
@@ -53,9 +53,10 @@ let slot_offset loc cl =
else !stack_offset + (num_stack_slots.(0) + n) * 8
| Outgoing n -> n
-(* Output a 32 bit integer in hex *)
+(* Output a 32 or 64 bit integer in hex *)
let emit_int32 n = emit_printf "0%lxh" n
+let emit_int64 n = emit_printf "0%Lxh" n
(* Symbols *)
@@ -321,36 +322,20 @@ let output_epilogue () =
(* Floating-point constants *)
-let float_constants = ref ([] : (string * int) list)
+let float_constants = ref ([] : (int64 * int) list)
let add_float_constant cst =
+ let repr = Int64.bits_of_float cst in
try
- List.assoc cst !float_constants
+ List.assoc repr !float_constants
with
Not_found ->
let lbl = new_label() in
- float_constants := (cst, lbl) :: !float_constants;
+ float_constants := (repr, lbl) :: !float_constants;
lbl
-let emit_float s =
- (* MASM doesn't like floating-point constants such as 2e9.
- Turn them into 2.0e9. *)
- let pos_e = ref (-1) and pos_dot = ref (-1) in
- for i = 0 to String.length s - 1 do
- match s.[i] with
- 'e'|'E' -> pos_e := i
- | '.' -> pos_dot := i
- | _ -> ()
- done;
- if !pos_dot < 0 && !pos_e >= 0 then begin
- emit_string (String.sub s 0 !pos_e);
- emit_string ".0";
- emit_string (String.sub s !pos_e (String.length s - !pos_e))
- end else
- emit_string s
-
let emit_float_constant (cst, lbl) =
- `{emit_label lbl} REAL8 {emit_float cst}\n`
+ `{emit_label lbl} QWORD {emit_int64 cst}\n`
let emit_movabs reg n =
(* force ml64 to use mov reg, imm64 instruction *)
@@ -389,12 +374,12 @@ let emit_instr fallthrough i =
` mov {emit_reg32 i.res.(0)}, {emit_nativeint n}\n`
else
emit_movabs i.res.(0) n
- | Lop(Iconst_float s) ->
- begin match Int64.bits_of_float (float_of_string s) with
+ | Lop(Iconst_float f) ->
+ begin match Int64.bits_of_float f with
| 0x0000_0000_0000_0000L -> (* +0.0 *)
` xorpd {emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
| _ ->
- let lbl = add_float_constant s in
+ let lbl = add_float_constant f in
` movsd {emit_reg i.res.(0)}, {emit_label lbl}\n`
end
| Lop(Iconst_symbol s) ->
@@ -458,7 +443,7 @@ let emit_instr fallthrough i =
| Double | Double_u ->
` movsd {emit_reg dest}, REAL8 PTR {emit_addressing addr i.arg 0}\n`
end
- | Lop(Istore(chunk, addr)) ->
+ | Lop(Istore(chunk, addr, _)) ->
begin match chunk with
| Word ->
` mov QWORD PTR {emit_addressing addr i.arg 1}, {emit_reg i.arg.(0)}\n`
@@ -547,9 +532,9 @@ let emit_instr fallthrough i =
` cvttsd2si {emit_reg i.res.(0)}, {emit_reg i.arg.(0)}\n`
| Lop(Ispecific(Ilea addr)) ->
` lea {emit_reg i.res.(0)}, {emit_addressing addr i.arg 0}\n`
- | Lop(Ispecific(Istore_int(n, addr))) ->
+ | Lop(Ispecific(Istore_int(n, addr, _))) ->
` mov QWORD PTR {emit_addressing addr i.arg 0}, {emit_nativeint n}\n`
- | Lop(Ispecific(Istore_symbol(s, addr))) ->
+ | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
assert (not !pic_code);
add_used_symbol s;
` mov QWORD PTR {emit_addressing addr i.arg 0}, OFFSET {emit_symbol s}\n`
@@ -721,9 +706,9 @@ let emit_item = function
| Cint n ->
` QWORD {emit_nativeint n}\n`
| Csingle f ->
- ` REAL4 {emit_float f}\n`
+ ` DWORD {emit_int32 (Int32.bits_of_float f)}\n`
| Cdouble f ->
- ` REAL8 {emit_float f}\n`
+ ` QWORD {emit_int64 (Int64.bits_of_float f)}\n`
| Csymbol_address s ->
add_used_symbol s;
` QWORD {emit_symbol s}\n`
diff --git a/asmcomp/amd64/proc.ml b/asmcomp/amd64/proc.ml
index b6e0fa94ab..e3f0d2950a 100644
--- a/asmcomp/amd64/proc.ml
+++ b/asmcomp/amd64/proc.ml
@@ -239,6 +239,10 @@ let loc_external_arguments =
let loc_exn_bucket = rax
+(* Volatile registers: none *)
+
+let regs_are_volatile rs = false
+
(* Registers destroyed by operations *)
let destroyed_at_c_call =
@@ -259,7 +263,7 @@ let destroyed_at_oper = function
| Iop(Iextcall(_, false)) -> destroyed_at_c_call
| Iop(Iintop(Idiv | Imod)) | Iop(Iintop_imm((Idiv | Imod), _))
-> [| rax; rdx |]
- | Iop(Istore(Single, _)) -> [| rxmm15 |]
+ | Iop(Istore(Single, _, _)) -> [| rxmm15 |]
| Iop(Ialloc _ | Iintop(Imulh | Icomp _) | Iintop_imm((Icomp _), _))
-> [| rax |]
| Iswitch(_, _) -> [| rax; rdx |]
@@ -290,10 +294,21 @@ let max_register_pressure = function
if fp then [| 10; 16 |] else [| 11; 16 |]
| Ialloc _ | Iintop(Icomp _) | Iintop_imm((Icomp _), _) ->
if fp then [| 11; 16 |] else [| 12; 16 |]
- | Istore(Single, _) ->
+ | Istore(Single, _, _) ->
if fp then [| 12; 15 |] else [| 13; 15 |]
| _ -> if fp then [| 12; 16 |] else [| 13; 16 |]
+(* Pure operations (without any side effect besides updating their result
+ registers). *)
+
+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 _ -> false
+ | _ -> true
+
(* Layout of the stack frame *)
let num_stack_slots = [| 0; 0 |]
diff --git a/asmcomp/amd64/selection.ml b/asmcomp/amd64/selection.ml
index 5e6afbcabf..fa7fe66c05 100644
--- a/asmcomp/amd64/selection.ml
+++ b/asmcomp/amd64/selection.ml
@@ -152,20 +152,20 @@ method select_addressing chunk exp =
| Ascaledadd(e1, e2, scale) ->
(Iindexed2scaled(scale, d), Ctuple[e1; e2])
-method! select_store addr exp =
+method! select_store is_assign addr exp =
match exp with
Cconst_int n when self#is_immediate n ->
- (Ispecific(Istore_int(Nativeint.of_int n, addr)), Ctuple [])
+ (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
| (Cconst_natint n | Cconst_blockheader n) when self#is_immediate_natint n ->
- (Ispecific(Istore_int(n, addr)), Ctuple [])
+ (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
| Cconst_pointer n when self#is_immediate n ->
- (Ispecific(Istore_int(Nativeint.of_int n, addr)), Ctuple [])
+ (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
| Cconst_natpointer n when self#is_immediate_natint n ->
- (Ispecific(Istore_int(n, addr)), Ctuple [])
+ (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
| Cconst_symbol s when not (!pic_code || !Clflags.dlcode) ->
- (Ispecific(Istore_symbol(s, addr)), Ctuple [])
+ (Ispecific(Istore_symbol(s, addr, is_assign)), Ctuple [])
| _ ->
- super#select_store addr exp
+ super#select_store is_assign addr exp
method! select_operation op args =
match op with
diff --git a/asmcomp/arm/CSE.ml b/asmcomp/arm/CSE.ml
new file mode 100644
index 0000000000..00282f1f55
--- /dev/null
+++ b/asmcomp/arm/CSE.ml
@@ -0,0 +1,38 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* CSE for ARM *)
+
+open Arch
+open Mach
+open CSEgen
+
+class cse = object (self)
+
+inherit cse_generic as super
+
+method! class_of_operation op =
+ match op with
+ | Ispecific(Ishiftcheckbound _) -> Op_checkbound
+ | Ispecific _ -> Op_pure
+ | _ -> super#class_of_operation op
+
+method! is_cheap_operation op =
+ match op with
+ | Iconst_int n | Iconst_blockheader n -> n <= 255n && n >= 0n
+ | _ -> false
+
+end
+
+let fundecl f =
+ (new cse)#fundecl f
+
diff --git a/asmcomp/arm/emit.mlp b/asmcomp/arm/emit.mlp
index 2f20ecf61a..61035b85fd 100644
--- a/asmcomp/arm/emit.mlp
+++ b/asmcomp/arm/emit.mlp
@@ -273,7 +273,7 @@ let function_name = ref ""
(* Entry point for tail recursive calls *)
let tailrec_entry_point = ref 0
(* Pending floating-point literals *)
-let float_literals = ref ([] : (string * label) list)
+let float_literals = ref ([] : (int64 * label) list)
(* Pending relative references to the global offset table *)
let gotrel_literals = ref ([] : (label * label) list)
(* Pending symbol literals *)
@@ -283,12 +283,13 @@ let num_literals = ref 0
(* Label a floating-point literal *)
let float_literal f =
+ let repr = Int64.bits_of_float f in
try
- List.assoc f !float_literals
+ List.assoc repr !float_literals
with Not_found ->
let lbl = new_label() in
num_literals := !num_literals + 2;
- float_literals := (f, lbl) :: !float_literals;
+ float_literals := (repr, lbl) :: !float_literals;
lbl
(* Label a GOTREL literal *)
@@ -314,7 +315,7 @@ let emit_literals() =
` .align 3\n`;
List.iter
(fun (f, lbl) ->
- `{emit_label lbl}: .double {emit_string f}\n`)
+ `{emit_label lbl}:`; emit_float64_split_directive ".long" f)
!float_literals;
float_literals := []
end;
@@ -390,8 +391,7 @@ let emit_instr i =
| Lop(Iconst_int n | Iconst_blockheader n) ->
emit_intconst i.res.(0) (Nativeint.to_int32 n)
| Lop(Iconst_float f) when !fpu = Soft ->
- ` @ {emit_string f}\n`;
- let bits = Int64.bits_of_float (float_of_string f) in
+ let bits = Int64.bits_of_float f in
let high_bits = Int64.to_int32 (Int64.shift_right_logical bits 32)
and low_bits = Int64.to_int32 bits in
if is_immediate low_bits || is_immediate high_bits then begin
@@ -406,7 +406,7 @@ let emit_instr i =
end
| Lop(Iconst_float f) when !fpu = VFPv2 ->
let lbl = float_literal f in
- ` fldd {emit_reg i.res.(0)}, {emit_label lbl} @ {emit_string f}\n`;
+ ` fldd {emit_reg i.res.(0)}, {emit_label lbl}\n`;
1
| Lop(Iconst_float f) ->
let encode imm =
@@ -425,12 +425,12 @@ let emit_instr i =
let ex = ((ex + 3) land 0x07) lxor 0x04 in
Some((sg lsl 7) lor (ex lsl 4) lor mn)
end in
- begin match encode (Int64.bits_of_float (float_of_string f)) with
+ begin match encode (Int64.bits_of_float f) with
None ->
let lbl = float_literal f in
- ` fldd {emit_reg i.res.(0)}, {emit_label lbl} @ {emit_string f}\n`
+ ` fldd {emit_reg i.res.(0)}, {emit_label lbl}\n`
| Some imm8 ->
- ` fconstd {emit_reg i.res.(0)}, #{emit_int imm8} @ {emit_string f}\n`
+ ` fconstd {emit_reg i.res.(0)}, #{emit_int imm8}\n`
end; 1
| Lop(Iconst_symbol s) ->
emit_load_symbol_addr i.res.(0) s
@@ -508,10 +508,10 @@ let emit_instr i =
| Double_u -> "fldd"
| _ (* 32-bit quantities *) -> "ldr" in
` {emit_string instr} {emit_reg r}, {emit_addressing addr i.arg 0}\n`; 1
- | Lop(Istore(Single, addr)) when !fpu >= VFPv2 ->
+ | Lop(Istore(Single, addr, _)) when !fpu >= VFPv2 ->
` fcvtsd s14, {emit_reg i.arg.(0)}\n`;
` fsts s14, {emit_addressing addr i.arg 1}\n`; 2
- | Lop(Istore((Double | Double_u), addr)) when !fpu = Soft ->
+ | Lop(Istore((Double | Double_u), addr, _)) when !fpu = Soft ->
(* Use STM or STRD if possible *)
begin match i.arg.(0), i.arg.(1), addr with
{loc = Reg rt}, {loc = Reg rt2}, Iindexed 0
@@ -525,7 +525,7 @@ let emit_instr i =
` str {emit_reg i.arg.(0)}, {emit_addressing addr i.arg 2}\n`;
` str {emit_reg i.arg.(1)}, {emit_addressing addr' i.arg 2}\n`; 2
end
- | Lop(Istore(size, addr)) ->
+ | Lop(Istore(size, addr, _)) ->
let r = i.arg.(0) in
let instr =
match size with
@@ -874,8 +874,8 @@ let emit_item = function
| Cint16 n -> ` .short {emit_int n}\n`
| Cint32 n -> ` .long {emit_int32 (Nativeint.to_int32 n)}\n`
| Cint n -> ` .long {emit_int32 (Nativeint.to_int32 n)}\n`
- | Csingle f -> ` .single {emit_string f}\n`
- | Cdouble f -> ` .double {emit_string f}\n`
+ | Csingle f -> emit_float32_directive ".long" (Int32.bits_of_float f)
+ | Cdouble f -> emit_float64_split_directive ".long" (Int64.bits_of_float f)
| Csymbol_address s -> ` .word {emit_symbol s}\n`
| Clabel_address lbl -> ` .word {emit_data_label lbl}\n`
| Cstring s -> emit_string_directive " .ascii " s
diff --git a/asmcomp/arm/proc.ml b/asmcomp/arm/proc.ml
index a16c35a226..99c59dd9cb 100644
--- a/asmcomp/arm/proc.ml
+++ b/asmcomp/arm/proc.ml
@@ -166,13 +166,17 @@ let loc_external_results res =
let loc_exn_bucket = phys_reg 0
+(* Volatile registers: none *)
+
+let regs_are_volatile rs = false
+
(* Registers destroyed by operations *)
let destroyed_at_alloc = (* r0-r6, d0-d15 preserved *)
Array.of_list (List.map
phys_reg
[7;8;
- 116;116;118;119;120;121;122;123;
+ 116;117;118;119;120;121;122;123;
124;125;126;127;128;129;130;131])
let destroyed_at_c_call =
@@ -183,12 +187,12 @@ let destroyed_at_c_call =
[0;1;2;3;8;
100;101;102;103;104;105;106;107;
108;109;110;111;112;113;114;115;
- 116;116;118;119;120;121;122;123;
+ 116;117;118;119;120;121;122;123;
124;125;126;127;128;129;130;131]
| EABI_HF -> (* r4-r7, d8-d15 preserved *)
[0;1;2;3;8;
100;101;102;103;104;105;106;107;
- 116;116;118;119;120;121;122;123;
+ 116;117;118;119;120;121;122;123;
124;125;126;127;128;129;130;131]))
let destroyed_at_oper = function
@@ -203,7 +207,7 @@ let destroyed_at_oper = function
[| phys_reg 3; phys_reg 8 |] (* r3 and r12 destroyed *)
| Iop(Iintop Imulh) when !arch < ARMv6 ->
[| phys_reg 8 |] (* r12 destroyed *)
- | Iop(Iintoffloat | Ifloatofint | Iload(Single, _) | Istore(Single, _)) ->
+ | Iop(Iintoffloat | Ifloatofint | Iload(Single, _) | Istore(Single, _, _)) ->
[| phys_reg 107 |] (* d7 (s14-s15) destroyed *)
| _ -> [||]
@@ -222,9 +226,19 @@ let max_register_pressure = function
| Ialloc _ -> if abi = EABI then [| 7; 0; 0 |] else [| 7; 8; 8 |]
| Iconst_symbol _ when !pic_code -> [| 7; 16; 32 |]
| Iintoffloat | Ifloatofint
- | Iload(Single, _) | Istore(Single, _) -> [| 9; 15; 31 |]
+ | Iload(Single, _) | Istore(Single, _, _) -> [| 9; 15; 31 |]
| _ -> [| 9; 16; 32 |]
+(* Pure operations (without any side effect besides updating their result
+ registers). *)
+
+let op_is_pure = function
+ | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+ | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
+ | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _)
+ | Ispecific(Ishiftcheckbound _) -> false
+ | _ -> true
+
(* Layout of the stack *)
let num_stack_slots = [| 0; 0; 0 |]
diff --git a/asmcomp/arm64/CSE.ml b/asmcomp/arm64/CSE.ml
new file mode 100644
index 0000000000..359e57eb55
--- /dev/null
+++ b/asmcomp/arm64/CSE.ml
@@ -0,0 +1,38 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* CSE for ARM64 *)
+
+open Arch
+open Mach
+open CSEgen
+
+class cse = object (self)
+
+inherit cse_generic as super
+
+method! class_of_operation op =
+ match op with
+ | Ispecific(Ishiftcheckbound _) -> Op_checkbound
+ | Ispecific _ -> Op_pure
+ | _ -> super#class_of_operation op
+
+method! is_cheap_operation op =
+ match op with
+ | Iconst_int n | Iconst_blockheader n -> n <= 65535n && n >= 0n
+ | _ -> false
+
+end
+
+let fundecl f =
+ (new cse)#fundecl f
+
diff --git a/asmcomp/arm64/emit.mlp b/asmcomp/arm64/emit.mlp
index 4a3e3cd7b4..734bd23e15 100644
--- a/asmcomp/arm64/emit.mlp
+++ b/asmcomp/arm64/emit.mlp
@@ -286,7 +286,7 @@ let emit_literals() =
` .align 3\n`;
List.iter
(fun (f, lbl) ->
- `{emit_label lbl}: .quad `; emit_printf "0x%Lx\n" f)
+ `{emit_label lbl}:`; emit_float64_directive ".quad" f)
!float_literals;
float_literals := []
end
@@ -326,15 +326,15 @@ let emit_instr i =
| Lop(Iconst_int n | Iconst_blockheader n) ->
emit_intconst i.res.(0) n
| Lop(Iconst_float f) ->
- let b = Int64.bits_of_float(float_of_string f) in
+ let b = Int64.bits_of_float f in
if b = 0L then
- ` fmov {emit_reg i.res.(0)}, xzr /* {emit_string f} */\n`
+ ` fmov {emit_reg i.res.(0)}, xzr\n`
else if is_immediate_float b then
- ` fmov {emit_reg i.res.(0)}, #{emit_printf "0x%Lx" b} /* {emit_string f} */\n`
+ ` fmov {emit_reg i.res.(0)}, #{emit_printf "0x%Lx" b}\n`
else begin
let lbl = float_literal b in
` adrp {emit_reg reg_tmp1}, {emit_label lbl}\n`;
- ` ldr {emit_reg i.res.(0)}, [{emit_reg reg_tmp1}, #:lo12:{emit_label lbl}] /* {emit_string f} */\n`
+ ` ldr {emit_reg i.res.(0)}, [{emit_reg reg_tmp1}, #:lo12:{emit_label lbl}]\n`
end
| Lop(Iconst_symbol s) ->
emit_load_symbol_addr i.res.(0) s
@@ -388,7 +388,7 @@ let emit_instr i =
| Word | Double | Double_u ->
` ldr {emit_reg dst}, {emit_addressing addr base}\n`
end
- | Lop(Istore(size, addr)) ->
+ | Lop(Istore(size, addr, _)) ->
let src = i.arg.(0) in
let base =
match addr with
@@ -644,7 +644,7 @@ let fundecl fundecl =
call_gc_sites := [];
bound_error_sites := [];
` .text\n`;
- ` .align 2\n`;
+ ` .align 3\n`;
` .globl {emit_symbol fundecl.fun_name}\n`;
` .type {emit_symbol fundecl.fun_name}, %function\n`;
`{emit_symbol fundecl.fun_name}:\n`;
@@ -675,8 +675,8 @@ let emit_item = function
| Cint16 n -> ` .short {emit_int n}\n`
| Cint32 n -> ` .long {emit_nativeint n}\n`
| Cint n -> ` .quad {emit_nativeint n}\n`
- | Csingle f -> emit_float32_directive ".long" f
- | Cdouble f -> emit_float64_directive ".quad" f
+ | Csingle f -> emit_float32_directive ".long" (Int32.bits_of_float f)
+ | Cdouble f -> emit_float64_directive ".quad" (Int64.bits_of_float f)
| Csymbol_address s -> ` .quad {emit_symbol s}\n`
| Clabel_address lbl -> ` .quad {emit_data_label lbl}\n`
| Cstring s -> emit_string_directive " .ascii " s
@@ -685,6 +685,7 @@ let emit_item = function
let data l =
` .data\n`;
+ ` .align 3\n`;
List.iter emit_item l
(* Beginning / end of an assembly file *)
diff --git a/asmcomp/arm64/proc.ml b/asmcomp/arm64/proc.ml
index b52c2fd8ae..9e19d477f5 100644
--- a/asmcomp/arm64/proc.ml
+++ b/asmcomp/arm64/proc.ml
@@ -160,6 +160,10 @@ let loc_external_results res =
let loc_exn_bucket = phys_reg 0
+(* Volatile registers: none *)
+
+let regs_are_volatile rs = false
+
(* Registers destroyed by operations *)
let destroyed_at_c_call =
@@ -177,7 +181,7 @@ let destroyed_at_oper = function
destroyed_at_c_call
| Iop(Ialloc _) ->
[| reg_x15 |]
- | Iop(Iintoffloat | Ifloatofint | Iload(Single, _) | Istore(Single, _)) ->
+ | Iop(Iintoffloat | Ifloatofint | Iload(Single, _) | Istore(Single, _, _)) ->
[| reg_d7 |] (* d7 / s7 destroyed *)
| _ -> [||]
@@ -194,9 +198,19 @@ let max_register_pressure = function
| Iextcall(_, _) -> [| 10; 8 |]
| Ialloc _ -> [| 25; 32 |]
| Iintoffloat | Ifloatofint
- | Iload(Single, _) | Istore(Single, _) -> [| 26; 31 |]
+ | Iload(Single, _) | Istore(Single, _, _) -> [| 26; 31 |]
| _ -> [| 26; 32 |]
+(* Pure operations (without any side effect besides updating their result
+ registers). *)
+
+let op_is_pure = function
+ | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+ | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
+ | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _)
+ | Ispecific(Ishiftcheckbound _) -> false
+ | _ -> true
+
(* Layout of the stack *)
let num_stack_slots = [| 0; 0 |]
diff --git a/asmcomp/asmgen.ml b/asmcomp/asmgen.ml
index 34283875cb..311bb029b2 100644
--- a/asmcomp/asmgen.ml
+++ b/asmcomp/asmgen.ml
@@ -64,7 +64,10 @@ let compile_fundecl (ppf : formatter) fd_cmm =
++ pass_dump_if ppf dump_selection "After instruction selection"
++ Comballoc.fundecl
++ pass_dump_if ppf dump_combine "After allocation combining"
+ ++ CSE.fundecl
+ ++ pass_dump_if ppf dump_cse "After CSE"
++ liveness ppf
+ ++ Deadcode.fundecl
++ pass_dump_if ppf dump_live "Liveness analysis"
++ Spill.fundecl
++ liveness ppf
diff --git a/asmcomp/asmlink.ml b/asmcomp/asmlink.ml
index 5842f44eb4..f0ca7ba296 100644
--- a/asmcomp/asmlink.ml
+++ b/asmcomp/asmlink.ml
@@ -33,31 +33,37 @@ exception Error of error
(* Consistency check between interfaces and implementations *)
let crc_interfaces = Consistbl.create ()
+let interfaces = ref ([] : string list)
let crc_implementations = Consistbl.create ()
-let extra_implementations = ref ([] : string list)
+let implementations = ref ([] : string list)
let implementations_defined = ref ([] : (string * string) list)
let cmx_required = ref ([] : string list)
let check_consistency file_name unit crc =
begin try
List.iter
- (fun (name, crc) ->
- if name = unit.ui_name
- then Consistbl.set crc_interfaces name crc file_name
- else Consistbl.check crc_interfaces name crc file_name)
+ (fun (name, crco) ->
+ interfaces := name :: !interfaces;
+ match crco with
+ None -> ()
+ | Some crc ->
+ if name = unit.ui_name
+ then Consistbl.set crc_interfaces name crc file_name
+ else Consistbl.check crc_interfaces name crc file_name)
unit.ui_imports_cmi
with Consistbl.Inconsistency(name, user, auth) ->
raise(Error(Inconsistent_interface(name, user, auth)))
end;
begin try
List.iter
- (fun (name, crc) ->
- if crc <> cmx_not_found_crc then
- Consistbl.check crc_implementations name crc file_name
- else if List.mem name !cmx_required then
- raise(Error(Missing_cmx(file_name, name)))
- else
- extra_implementations := name :: !extra_implementations)
+ (fun (name, crco) ->
+ implementations := name :: !implementations;
+ match crco with
+ None ->
+ if List.mem name !cmx_required then
+ raise(Error(Missing_cmx(file_name, name)))
+ | Some crc ->
+ Consistbl.check crc_implementations name crc file_name)
unit.ui_imports_cmx
with Consistbl.Inconsistency(name, user, auth) ->
raise(Error(Inconsistent_implementation(name, user, auth)))
@@ -67,6 +73,7 @@ let check_consistency file_name unit crc =
raise (Error(Multiple_definition(unit.ui_name, file_name, source)))
with Not_found -> ()
end;
+ implementations := unit.ui_name :: !implementations;
Consistbl.set crc_implementations unit.ui_name crc file_name;
implementations_defined :=
(unit.ui_name, file_name) :: !implementations_defined;
@@ -74,13 +81,9 @@ let check_consistency file_name unit crc =
cmx_required := unit.ui_name :: !cmx_required
let extract_crc_interfaces () =
- Consistbl.extract crc_interfaces
+ Consistbl.extract !interfaces crc_interfaces
let extract_crc_implementations () =
- List.fold_left
- (fun ncl n ->
- if List.mem_assoc n ncl then ncl else (n, cmx_not_found_crc) :: ncl)
- (Consistbl.extract crc_implementations)
- !extra_implementations
+ Consistbl.extract !implementations crc_implementations
(* Add C objects and options and "custom" info from a library descriptor.
See bytecomp/bytelink.ml for comments on the order of C objects. *)
@@ -214,10 +217,14 @@ let make_startup_file ppf filename units_list =
(Cmmgen.globals_map
(List.map
(fun (unit,_,crc) ->
- try (unit.ui_name, List.assoc unit.ui_name unit.ui_imports_cmi,
- crc,
- unit.ui_defines)
- with Not_found -> assert false)
+ 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));
compile_phrase(Cmmgen.data_segment_table ("_startup" :: name_list));
compile_phrase(Cmmgen.code_segment_table ("_startup" :: name_list));
@@ -397,3 +404,14 @@ let () =
| Error err -> Some (Location.error_of_printer_file report_error err)
| _ -> None
)
+
+let reset () =
+ Consistbl.clear crc_interfaces;
+ Consistbl.clear crc_implementations;
+ implementations_defined := [];
+ cmx_required := [];
+ interfaces := [];
+ implementations := []
+
+
+
diff --git a/asmcomp/asmlink.mli b/asmcomp/asmlink.mli
index 1cf9e302c1..60a2111e1c 100644
--- a/asmcomp/asmlink.mli
+++ b/asmcomp/asmlink.mli
@@ -20,9 +20,10 @@ val link_shared: formatter -> string list -> string -> unit
val call_linker_shared: string list -> string -> unit
+val reset : unit -> unit
val check_consistency: string -> Cmx_format.unit_infos -> Digest.t -> unit
-val extract_crc_interfaces: unit -> (string * Digest.t) list
-val extract_crc_implementations: unit -> (string * Digest.t) list
+val extract_crc_interfaces: unit -> (string * Digest.t option) list
+val extract_crc_implementations: unit -> (string * Digest.t option) list
type error =
File_not_found of string
diff --git a/asmcomp/asmpackager.ml b/asmcomp/asmpackager.ml
index a8fcfe7896..d900df1e14 100644
--- a/asmcomp/asmpackager.ml
+++ b/asmcomp/asmpackager.ml
@@ -130,7 +130,7 @@ let build_package_cmx members cmxfile =
List.flatten (List.map (fun info -> info.ui_defines) units) @
[ui.ui_symbol];
ui_imports_cmi =
- (ui.ui_name, Env.crc_of_unit ui.ui_name) ::
+ (ui.ui_name, Some (Env.crc_of_unit ui.ui_name)) ::
filter(Asmlink.extract_crc_interfaces());
ui_imports_cmx =
filter(Asmlink.extract_crc_implementations());
@@ -161,7 +161,7 @@ let package_object_files ppf files targetcmx
(* The entry point *)
-let package_files ppf files targetcmx =
+let package_files ppf initial_env files targetcmx =
let files =
List.map
(fun f ->
@@ -177,7 +177,8 @@ let package_files ppf files targetcmx =
(* Set the name of the current compunit *)
Compilenv.reset ?packname:!Clflags.for_package targetname;
try
- let coercion = Typemod.package_units files targetcmi targetname in
+ let coercion =
+ Typemod.package_units initial_env files targetcmi targetname in
package_object_files ppf files targetcmx targetobj targetname coercion
with x ->
remove_file targetcmx; remove_file targetobj;
diff --git a/asmcomp/asmpackager.mli b/asmcomp/asmpackager.mli
index 65272b7ed7..4d47f5c283 100644
--- a/asmcomp/asmpackager.mli
+++ b/asmcomp/asmpackager.mli
@@ -13,7 +13,7 @@
(* "Package" a set of .cmx/.o files into one .cmx/.o file having the
original compilation units as sub-modules. *)
-val package_files: Format.formatter -> string list -> string -> unit
+val package_files: Format.formatter -> Env.t -> string list -> string -> unit
type error =
Illegal_renaming of string * string * string
diff --git a/asmcomp/clambda.ml b/asmcomp/clambda.ml
index 3586296e4f..ed96f218bf 100644
--- a/asmcomp/clambda.ml
+++ b/asmcomp/clambda.ml
@@ -19,12 +19,12 @@ open Lambda
type function_label = string
type ustructured_constant =
- | Uconst_float of string
+ | Uconst_float of float
| Uconst_int32 of int32
| Uconst_int64 of int64
| Uconst_nativeint of nativeint
| Uconst_block of int * uconstant list
- | Uconst_float_array of string list
+ | Uconst_float_array of float list
| Uconst_string of string
and uconstant =
@@ -74,7 +74,9 @@ 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: (Ident.t list * ulambda) option;
+ mutable fun_float_const_prop: bool (* Can propagate FP consts *)
+ }
(* Approximation of values *)
@@ -84,3 +86,65 @@ type value_approximation =
| Value_unknown
| Value_const of uconstant
| Value_global_field of string * int
+
+(* Comparison functions for constants. We must not use Pervasives.compare
+ because it compares "0.0" and "-0.0" equal. (PR#6442) *)
+
+let compare_floats x1 x2 =
+ Int64.compare (Int64.bits_of_float x1) (Int64.bits_of_float x2)
+
+let rec compare_float_lists l1 l2 =
+ match l1, l2 with
+ | [], [] -> 0
+ | [], _::_ -> -1
+ | _::_, [] -> 1
+ | h1::t1, h2::t2 ->
+ let c = compare_floats h1 h2 in
+ if c <> 0 then c else compare_float_lists t1 t2
+
+let compare_constants c1 c2 =
+ match c1, c2 with
+ | Uconst_ref(lbl1, c1), Uconst_ref(lbl2, c2) -> String.compare lbl1 lbl2
+ (* Same labels -> same constants.
+ 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_ref _, _ -> -1
+ | Uconst_int _, Uconst_ref _ -> 1
+ | Uconst_int _, Uconst_ptr _ -> -1
+ | Uconst_ptr _, _ -> 1
+
+let rec compare_constant_lists l1 l2 =
+ match l1, l2 with
+ | [], [] -> 0
+ | [], _::_ -> -1
+ | _::_, [] -> 1
+ | h1::t1, h2::t2 ->
+ let c = compare_constants h1 h2 in
+ if c <> 0 then c else compare_constant_lists t1 t2
+
+let rank_structured_constant = function
+ | Uconst_float _ -> 0
+ | Uconst_int32 _ -> 1
+ | Uconst_int64 _ -> 2
+ | Uconst_nativeint _ -> 3
+ | Uconst_block _ -> 4
+ | Uconst_float_array _ -> 5
+ | Uconst_string _ -> 6
+
+let compare_structured_constants c1 c2 =
+ match c1, c2 with
+ | Uconst_float x1, Uconst_float x2 -> compare_floats x1 x2
+ | Uconst_int32 x1, Uconst_int32 x2 -> Int32.compare x1 x2
+ | Uconst_int64 x1, Uconst_int64 x2 -> Int64.compare x1 x2
+ | Uconst_nativeint x1, Uconst_nativeint x2 -> Nativeint.compare x1 x2
+ | Uconst_block(t1, l1), Uconst_block(t2, l2) ->
+ let c = t1 - t2 (* no overflow possible here *) in
+ if c <> 0 then c else compare_constant_lists l1 l2
+ | Uconst_float_array l1, Uconst_float_array l2 ->
+ compare_float_lists l1 l2
+ | Uconst_string s1, Uconst_string s2 -> String.compare s1 s2
+ | _, _ -> rank_structured_constant c1 - rank_structured_constant c2
+ (* no overflow possible here *)
diff --git a/asmcomp/clambda.mli b/asmcomp/clambda.mli
index e751326fe4..fc7a14d1e2 100644
--- a/asmcomp/clambda.mli
+++ b/asmcomp/clambda.mli
@@ -19,12 +19,12 @@ open Lambda
type function_label = string
type ustructured_constant =
- | Uconst_float of string
+ | Uconst_float of float
| Uconst_int32 of int32
| Uconst_int64 of int64
| Uconst_nativeint of nativeint
| Uconst_block of int * uconstant list
- | Uconst_float_array of string list
+ | Uconst_float_array of float list
| Uconst_string of string
and uconstant =
@@ -74,7 +74,9 @@ 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: (Ident.t list * ulambda) option;
+ mutable fun_float_const_prop: bool (* Can propagate FP consts *)
+ }
(* Approximation of values *)
@@ -84,3 +86,10 @@ type value_approximation =
| Value_unknown
| Value_const of uconstant
| Value_global_field of string * int
+
+(* Comparison functions for constants *)
+
+val compare_structured_constants:
+ ustructured_constant -> ustructured_constant -> int
+val compare_constants:
+ uconstant -> uconstant -> int
diff --git a/asmcomp/closure.ml b/asmcomp/closure.ml
index eff35ce4f2..9d3749d44d 100644
--- a/asmcomp/closure.ml
+++ b/asmcomp/closure.ml
@@ -245,14 +245,15 @@ let rec is_pure_clambda = function
| Uprim(p, args, _) -> List.for_all is_pure_clambda args
| _ -> false
-(* Simplify primitive operations on integers *)
+(* Simplify primitive operations on known arguments *)
let make_const c = (Uconst c, Value_const c)
-
+let make_const_ref c =
+ make_const(Uconst_ref(Compilenv.new_structured_constant ~shared:true c, c))
let make_const_int n = make_const (Uconst_int n)
let make_const_ptr n = make_const (Uconst_ptr n)
let make_const_bool b = make_const_ptr(if b then 1 else 0)
-let make_comparison cmp (x: int) (y: int) =
+let make_comparison cmp x y =
make_const_bool
(match cmp with
Ceq -> x = y
@@ -261,71 +262,187 @@ let make_comparison cmp (x: int) (y: int) =
| Cgt -> x > y
| Cle -> x <= y
| Cge -> x >= y)
+let make_const_float n = make_const_ref (Uconst_float n)
+let make_const_natint n = make_const_ref (Uconst_nativeint n)
+let make_const_int32 n = make_const_ref (Uconst_int32 n)
+let make_const_int64 n = make_const_ref (Uconst_int64 n)
+
+(* The [fpc] parameter is true if constant propagation of
+ floating-point computations is allowed *)
-let simplif_int_prim_pure p (args, approxs) dbg =
+let simplif_arith_prim_pure fpc p (args, approxs) dbg =
+ let default = (Uprim(p, args, dbg), Value_unknown) in
match approxs with
- [Value_const (Uconst_int x)] ->
+ (* int (or enumerated type) *)
+ | [ Value_const(Uconst_int n1 | Uconst_ptr n1) ] ->
begin match p with
- Pidentity -> make_const_int x
- | Pnegint -> make_const_int (-x)
- | Pbswap16 ->
- make_const_int (((x land 0xff) lsl 8) lor
- ((x land 0xff00) lsr 8))
- | Poffsetint y -> make_const_int (x + y)
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Pnot -> make_const_bool (n1 = 0)
+ | Pnegint -> make_const_int (- n1)
+ | Poffsetint n -> make_const_int (n + n1)
+ | Pfloatofint when fpc -> make_const_float (float_of_int n1)
+ | Pbintofint Pnativeint -> make_const_natint (Nativeint.of_int n1)
+ | Pbintofint Pint32 -> make_const_int32 (Int32.of_int n1)
+ | Pbintofint Pint64 -> make_const_int64 (Int64.of_int n1)
+ | Pbswap16 -> make_const_int (((n1 land 0xff) lsl 8)
+ lor ((n1 land 0xff00) lsr 8))
+ | _ -> default
end
- | [Value_const (Uconst_int x); Value_const (Uconst_int y)] ->
+ (* int (or enumerated type), int (or enumerated type) *)
+ | [ Value_const(Uconst_int n1 | Uconst_ptr n1);
+ Value_const(Uconst_int n2 | Uconst_ptr n2) ] ->
begin match p with
- Paddint -> make_const_int(x + y)
- | Psubint -> make_const_int(x - y)
- | Pmulint -> make_const_int(x * y)
- | Pdivint when y <> 0 -> make_const_int(x / y)
- | Pmodint when y <> 0 -> make_const_int(x mod y)
- | Pandint -> make_const_int(x land y)
- | Porint -> make_const_int(x lor y)
- | Pxorint -> make_const_int(x lxor y)
- | Plslint -> make_const_int(x lsl y)
- | Plsrint -> make_const_int(x lsr y)
- | Pasrint -> make_const_int(x asr y)
- | Pintcomp cmp -> make_comparison cmp x y
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Psequand -> make_const_bool (n1 <> 0 && n2 <> 0)
+ | Psequor -> make_const_bool (n1 <> 0 || n2 <> 0)
+ | Paddint -> make_const_int (n1 + n2)
+ | Psubint -> make_const_int (n1 - n2)
+ | Pmulint -> make_const_int (n1 * n2)
+ | Pdivint when n2 <> 0 -> make_const_int (n1 / n2)
+ | Pmodint when n2 <> 0 -> make_const_int (n1 mod n2)
+ | Pandint -> make_const_int (n1 land n2)
+ | Porint -> make_const_int (n1 lor n2)
+ | Pxorint -> make_const_int (n1 lxor n2)
+ | Plslint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_int (n1 lsl n2)
+ | Plsrint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_int (n1 lsr n2)
+ | Pasrint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_int (n1 asr n2)
+ | Pintcomp c -> make_comparison c n1 n2
+ | _ -> default
end
- | [Value_const (Uconst_ptr x)] ->
+ (* float *)
+ | [Value_const(Uconst_ref(_, Uconst_float n1))] when fpc ->
begin match p with
- Pidentity -> make_const_ptr x
- | Pnot -> make_const_bool(x = 0)
- | Pisint -> make_const_bool true
- | Pctconst c ->
- begin
- match c with
- | Big_endian -> make_const_bool Arch.big_endian
- | Word_size -> make_const_int (8*Arch.size_int)
- | Ostype_unix -> make_const_bool (Sys.os_type = "Unix")
- | Ostype_win32 -> make_const_bool (Sys.os_type = "Win32")
- | Ostype_cygwin -> make_const_bool (Sys.os_type = "Cygwin")
- end
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Pintoffloat -> make_const_int (int_of_float n1)
+ | Pnegfloat -> make_const_float (-. n1)
+ | Pabsfloat -> make_const_float (abs_float n1)
+ | _ -> default
end
- | [Value_const (Uconst_ptr x); Value_const (Uconst_ptr y)] ->
+ (* float, float *)
+ | [Value_const(Uconst_ref(_, Uconst_float n1));
+ Value_const(Uconst_ref(_, Uconst_float n2))] when fpc ->
begin match p with
- Psequand -> make_const_bool(x <> 0 && y <> 0)
- | Psequor -> make_const_bool(x <> 0 || y <> 0)
- | Pintcomp cmp -> make_comparison cmp x y
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Paddfloat -> make_const_float (n1 +. n2)
+ | Psubfloat -> make_const_float (n1 -. n2)
+ | Pmulfloat -> make_const_float (n1 *. n2)
+ | Pdivfloat -> make_const_float (n1 /. n2)
+ | Pfloatcomp c -> make_comparison c n1 n2
+ | _ -> default
end
- | [Value_const (Uconst_ptr x); Value_const (Uconst_int y)] ->
+ (* nativeint *)
+ | [Value_const(Uconst_ref(_, Uconst_nativeint n))] ->
begin match p with
- | Pintcomp cmp -> make_comparison cmp x y
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Pintofbint Pnativeint -> make_const_int (Nativeint.to_int n)
+ | Pcvtbint(Pnativeint, Pint32) -> make_const_int32 (Nativeint.to_int32 n)
+ | Pcvtbint(Pnativeint, Pint64) -> make_const_int64 (Int64.of_nativeint n)
+ | Pnegbint Pnativeint -> make_const_natint (Nativeint.neg n)
+ | _ -> default
end
- | [Value_const (Uconst_int x); Value_const (Uconst_ptr y)] ->
+ (* nativeint, nativeint *)
+ | [Value_const(Uconst_ref(_, Uconst_nativeint n1));
+ Value_const(Uconst_ref(_, Uconst_nativeint n2))] ->
begin match p with
- | Pintcomp cmp -> make_comparison cmp x y
- | _ -> (Uprim(p, args, dbg), Value_unknown)
+ | Paddbint Pnativeint -> make_const_natint (Nativeint.add n1 n2)
+ | Psubbint Pnativeint -> make_const_natint (Nativeint.sub n1 n2)
+ | Pmulbint Pnativeint -> make_const_natint (Nativeint.mul n1 n2)
+ | Pdivbint Pnativeint when n2 <> 0n ->
+ make_const_natint (Nativeint.div n1 n2)
+ | Pmodbint Pnativeint when n2 <> 0n ->
+ make_const_natint (Nativeint.rem n1 n2)
+ | Pandbint Pnativeint -> make_const_natint (Nativeint.logand n1 n2)
+ | Porbint Pnativeint -> make_const_natint (Nativeint.logor n1 n2)
+ | Pxorbint Pnativeint -> make_const_natint (Nativeint.logxor n1 n2)
+ | Pbintcomp(Pnativeint, c) -> make_comparison c n1 n2
+ | _ -> default
+ end
+ (* nativeint, int *)
+ | [Value_const(Uconst_ref(_, Uconst_nativeint n1));
+ Value_const(Uconst_int n2)] ->
+ begin match p with
+ | Plslbint Pnativeint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_natint (Nativeint.shift_left n1 n2)
+ | Plsrbint Pnativeint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_natint (Nativeint.shift_right_logical n1 n2)
+ | Pasrbint Pnativeint when 0 <= n2 && n2 < 8 * Arch.size_int ->
+ make_const_natint (Nativeint.shift_right n1 n2)
+ | _ -> default
+ end
+ (* int32 *)
+ | [Value_const(Uconst_ref(_, Uconst_int32 n))] ->
+ begin match p with
+ | Pintofbint Pint32 -> make_const_int (Int32.to_int n)
+ | Pcvtbint(Pint32, Pnativeint) -> make_const_natint (Nativeint.of_int32 n)
+ | Pcvtbint(Pint32, Pint64) -> make_const_int64 (Int64.of_int32 n)
+ | Pnegbint Pint32 -> make_const_int32 (Int32.neg n)
+ | _ -> default
+ end
+ (* int32, int32 *)
+ | [Value_const(Uconst_ref(_, Uconst_int32 n1));
+ Value_const(Uconst_ref(_, Uconst_int32 n2))] ->
+ begin match p with
+ | Paddbint Pint32 -> make_const_int32 (Int32.add n1 n2)
+ | Psubbint Pint32 -> make_const_int32 (Int32.sub n1 n2)
+ | Pmulbint Pint32 -> make_const_int32 (Int32.mul n1 n2)
+ | Pdivbint Pint32 when n2 <> 0l -> make_const_int32 (Int32.div n1 n2)
+ | Pmodbint Pint32 when n2 <> 0l -> make_const_int32 (Int32.rem n1 n2)
+ | Pandbint Pint32 -> make_const_int32 (Int32.logand n1 n2)
+ | Porbint Pint32 -> make_const_int32 (Int32.logor n1 n2)
+ | Pxorbint Pint32 -> make_const_int32 (Int32.logxor n1 n2)
+ | Pbintcomp(Pint32, c) -> make_comparison c n1 n2
+ | _ -> default
+ end
+ (* int32, int *)
+ | [Value_const(Uconst_ref(_, Uconst_int32 n1));
+ Value_const(Uconst_int n2)] ->
+ begin match p with
+ | Plslbint Pint32 when 0 <= n2 && n2 < 32 ->
+ make_const_int32 (Int32.shift_left n1 n2)
+ | Plsrbint Pint32 when 0 <= n2 && n2 < 32 ->
+ make_const_int32 (Int32.shift_right_logical n1 n2)
+ | Pasrbint Pint32 when 0 <= n2 && n2 < 32 ->
+ make_const_int32 (Int32.shift_right n1 n2)
+ | _ -> default
end
+ (* int64 *)
+ | [Value_const(Uconst_ref(_, Uconst_int64 n))] ->
+ begin match p with
+ | Pintofbint Pint64 -> make_const_int (Int64.to_int n)
+ | Pcvtbint(Pint64, Pint32) -> make_const_int32 (Int64.to_int32 n)
+ | Pcvtbint(Pint64, Pnativeint) -> make_const_natint (Int64.to_nativeint n)
+ | Pnegbint Pint64 -> make_const_int64 (Int64.neg n)
+ | _ -> default
+ end
+ (* int64, int64 *)
+ | [Value_const(Uconst_ref(_, Uconst_int64 n1));
+ Value_const(Uconst_ref(_, Uconst_int64 n2))] ->
+ begin match p with
+ | Paddbint Pint64 -> make_const_int64 (Int64.add n1 n2)
+ | Psubbint Pint64 -> make_const_int64 (Int64.sub n1 n2)
+ | Pmulbint Pint64 -> make_const_int64 (Int64.mul n1 n2)
+ | Pdivbint Pint64 when n2 <> 0L -> make_const_int64 (Int64.div n1 n2)
+ | Pmodbint Pint64 when n2 <> 0L -> make_const_int64 (Int64.rem n1 n2)
+ | Pandbint Pint64 -> make_const_int64 (Int64.logand n1 n2)
+ | Porbint Pint64 -> make_const_int64 (Int64.logor n1 n2)
+ | Pxorbint Pint64 -> make_const_int64 (Int64.logxor n1 n2)
+ | Pbintcomp(Pint64, c) -> make_comparison c n1 n2
+ | _ -> default
+ end
+ (* int64, int *)
+ | [Value_const(Uconst_ref(_, Uconst_int64 n1));
+ Value_const(Uconst_int n2)] ->
+ begin match p with
+ | Plslbint Pint64 when 0 <= n2 && n2 < 64 ->
+ make_const_int64 (Int64.shift_left n1 n2)
+ | Plsrbint Pint64 when 0 <= n2 && n2 < 64 ->
+ make_const_int64 (Int64.shift_right_logical n1 n2)
+ | Pasrbint Pint64 when 0 <= n2 && n2 < 64 ->
+ make_const_int64 (Int64.shift_right n1 n2)
+ | _ -> default
+ end
+ (* TODO: Pbbswap *)
+ (* Catch-all *)
| _ ->
- (Uprim(p, args, dbg), Value_unknown)
-
+ default
let field_approx n = function
| Value_tuple a when n < Array.length a -> a.(n)
@@ -333,8 +450,9 @@ let field_approx n = function
Value_const (List.nth l n)
| _ -> Value_unknown
-let simplif_prim_pure p (args, approxs) dbg =
+let simplif_prim_pure fpc p (args, approxs) dbg =
match p, args, approxs with
+ (* Block construction *)
| Pmakeblock(tag, Immutable), _, _ ->
let field = function
| Value_const c -> c
@@ -349,24 +467,43 @@ let simplif_prim_pure p (args, approxs) dbg =
with Exit ->
(Uprim(p, args, dbg), Value_tuple (Array.of_list approxs))
end
+ (* Field access *)
| Pfield n, _, [ Value_const(Uconst_ref(_, Uconst_block(_, l))) ]
when n < List.length l ->
make_const (List.nth l n)
-
- | Pfield n, [ Uprim(Pmakeblock _, ul, _) ], [approx] ->
- assert(n < List.length ul);
- List.nth ul n, field_approx n approx
-
- | Pstringlength, _, [ Value_const(Uconst_ref(_, Uconst_string s)) ]
- ->
+ | Pfield n, [ Uprim(Pmakeblock _, ul, _) ], [approx]
+ when n < List.length ul ->
+ (List.nth ul n, field_approx n approx)
+ (* Strings *)
+ | Pstringlength, _, [ Value_const(Uconst_ref(_, Uconst_string s)) ] ->
make_const_int (String.length s)
-
+ (* Identity *)
+ | Pidentity, [arg1], [app1] ->
+ (arg1, app1)
+ (* Kind test *)
+ | Pisint, _, [a1] ->
+ begin match a1 with
+ | Value_const(Uconst_int _ | Uconst_ptr _) -> make_const_bool true
+ | Value_const(Uconst_ref _) -> make_const_bool false
+ | Value_closure _ | Value_tuple _ -> make_const_bool false
+ | _ -> (Uprim(p, args, dbg), Value_unknown)
+ end
+ (* Compile-time constants *)
+ | Pctconst c, _, _ ->
+ begin match c with
+ | Big_endian -> make_const_bool Arch.big_endian
+ | Word_size -> make_const_int (8*Arch.size_int)
+ | Ostype_unix -> make_const_bool (Sys.os_type = "Unix")
+ | Ostype_win32 -> make_const_bool (Sys.os_type = "Win32")
+ | Ostype_cygwin -> make_const_bool (Sys.os_type = "Cygwin")
+ end
+ (* Catch-all *)
| _ ->
- simplif_int_prim_pure p (args, approxs) dbg
+ simplif_arith_prim_pure fpc p (args, approxs) dbg
-let simplif_prim p (args, approxs as args_approxs) dbg =
+let simplif_prim fpc p (args, approxs as args_approxs) dbg =
if List.for_all is_pure_clambda args
- then simplif_prim_pure p args_approxs dbg
+ then simplif_prim_pure fpc p args_approxs dbg
else
(* XXX : always return the same approxs as simplif_prim_pure? *)
let approx =
@@ -391,15 +528,16 @@ let approx_ulam = function
Uconst c -> Value_const c
| _ -> Value_unknown
-let rec substitute sb ulam =
+let rec substitute fpc sb ulam =
match ulam with
Uvar v ->
begin try Tbl.find v sb with Not_found -> ulam end
| Uconst _ -> ulam
| Udirect_apply(lbl, args, dbg) ->
- Udirect_apply(lbl, List.map (substitute sb) args, dbg)
+ Udirect_apply(lbl, List.map (substitute fpc sb) args, dbg)
| Ugeneric_apply(fn, args, dbg) ->
- Ugeneric_apply(substitute sb fn, List.map (substitute sb) args, dbg)
+ Ugeneric_apply(substitute fpc sb fn,
+ List.map (substitute fpc sb) args, dbg)
| Uclosure(defs, env) ->
(* Question: should we rename function labels as well? Otherwise,
there is a risk that function labels are not globally unique.
@@ -409,11 +547,12 @@ let rec substitute sb ulam =
- When we substitute offsets for idents bound by let rec
in [close], case [Lletrec], we discard the original
let rec body and use only the substituted term. *)
- Uclosure(defs, List.map (substitute sb) env)
- | Uoffset(u, ofs) -> Uoffset(substitute sb u, ofs)
+ Uclosure(defs, List.map (substitute fpc sb) env)
+ | Uoffset(u, ofs) -> Uoffset(substitute fpc sb u, ofs)
| Ulet(id, u1, u2) ->
let id' = Ident.rename id in
- Ulet(id', substitute sb u1, substitute (Tbl.add id (Uvar id') sb) u2)
+ Ulet(id', substitute fpc sb u1,
+ substitute fpc (Tbl.add id (Uvar id') sb) u2)
| Uletrec(bindings, body) ->
let bindings1 =
List.map (fun (id, rhs) -> (id, Ident.rename id, rhs)) bindings in
@@ -422,57 +561,64 @@ let rec substitute sb ulam =
(fun (id, id', _) s -> Tbl.add id (Uvar id') s)
bindings1 sb in
Uletrec(
- List.map (fun (id, id', rhs) -> (id', substitute sb' rhs)) bindings1,
- substitute sb' body)
+ List.map
+ (fun (id, id', rhs) -> (id', substitute fpc sb' rhs))
+ bindings1,
+ substitute fpc sb' body)
| Uprim(p, args, dbg) ->
- let sargs = List.map (substitute sb) args in
- let (res, _) = simplif_prim p (sargs, List.map approx_ulam sargs) dbg in
+ let sargs =
+ List.map (substitute fpc sb) args in
+ let (res, _) =
+ simplif_prim fpc p (sargs, List.map approx_ulam sargs) dbg in
res
| Uswitch(arg, sw) ->
- Uswitch(substitute sb arg,
+ Uswitch(substitute fpc sb arg,
{ sw with
us_actions_consts =
- Array.map (substitute sb) sw.us_actions_consts;
+ Array.map (substitute fpc sb) sw.us_actions_consts;
us_actions_blocks =
- Array.map (substitute sb) sw.us_actions_blocks;
+ Array.map (substitute fpc sb) sw.us_actions_blocks;
})
| Ustringswitch(arg,sw,d) ->
Ustringswitch
- (substitute sb arg,
- List.map (fun (s,act) -> s,substitute sb act) sw,
- Misc.may_map (substitute sb) d)
+ (substitute fpc sb arg,
+ List.map (fun (s,act) -> s,substitute fpc sb act) sw,
+ Misc.may_map (substitute fpc sb) d)
| Ustaticfail (nfail, args) ->
- Ustaticfail (nfail, List.map (substitute sb) args)
+ Ustaticfail (nfail, List.map (substitute fpc sb) args)
| Ucatch(nfail, ids, u1, u2) ->
- Ucatch(nfail, ids, substitute sb u1, substitute sb u2)
+ Ucatch(nfail, ids, substitute fpc sb u1, substitute fpc sb u2)
| Utrywith(u1, id, u2) ->
let id' = Ident.rename id in
- Utrywith(substitute sb u1, id', substitute (Tbl.add id (Uvar id') sb) u2)
+ Utrywith(substitute fpc sb u1, id',
+ substitute fpc (Tbl.add id (Uvar id') sb) u2)
| Uifthenelse(u1, u2, u3) ->
- begin match substitute sb u1 with
+ begin match substitute fpc sb u1 with
Uconst (Uconst_ptr n) ->
- if n <> 0 then substitute sb u2 else substitute sb u3
+ if n <> 0 then substitute fpc sb u2 else substitute fpc sb u3
| Uprim(Pmakeblock _, _, _) ->
- substitute sb u2
+ substitute fpc sb u2
| su1 ->
- Uifthenelse(su1, substitute sb u2, substitute sb u3)
+ Uifthenelse(su1, substitute fpc sb u2, substitute fpc sb u3)
end
- | Usequence(u1, u2) -> Usequence(substitute sb u1, substitute sb u2)
- | Uwhile(u1, u2) -> Uwhile(substitute sb u1, substitute sb u2)
+ | Usequence(u1, u2) ->
+ Usequence(substitute fpc sb u1, substitute fpc sb u2)
+ | Uwhile(u1, u2) ->
+ Uwhile(substitute fpc sb u1, substitute fpc sb u2)
| Ufor(id, u1, u2, dir, u3) ->
let id' = Ident.rename id in
- Ufor(id', substitute sb u1, substitute sb u2, dir,
- substitute (Tbl.add id (Uvar id') sb) u3)
+ Ufor(id', substitute fpc sb u1, substitute fpc sb u2, dir,
+ substitute fpc (Tbl.add id (Uvar id') sb) u3)
| Uassign(id, u) ->
let id' =
try
match Tbl.find id sb with Uvar i -> i | _ -> assert false
with Not_found ->
id in
- Uassign(id', substitute sb u)
+ Uassign(id', substitute fpc sb u)
| Usend(k, u1, u2, ul, dbg) ->
- Usend(k, substitute sb u1, substitute sb u2, List.map (substitute sb) ul,
- dbg)
+ Usend(k, substitute fpc sb u1, substitute fpc sb u2,
+ List.map (substitute fpc sb) ul, dbg)
(* Perform an inline expansion *)
@@ -484,12 +630,12 @@ let no_effects = function
| Uclosure _ -> true
| u -> is_simple_argument u
-let rec bind_params_rec subst params args body =
+let rec bind_params_rec fpc subst params args body =
match (params, args) with
- ([], []) -> substitute subst body
+ ([], []) -> substitute fpc subst body
| (p1 :: pl, a1 :: al) ->
if is_simple_argument a1 then
- bind_params_rec (Tbl.add p1 a1 subst) pl al body
+ bind_params_rec fpc (Tbl.add p1 a1 subst) pl al body
else begin
let p1' = Ident.rename p1 in
let u1, u2 =
@@ -500,17 +646,17 @@ let rec bind_params_rec subst params args body =
a1, Uvar p1'
in
let body' =
- bind_params_rec (Tbl.add p1 u2 subst) pl al body in
+ bind_params_rec fpc (Tbl.add p1 u2 subst) pl al body in
if occurs_var p1 body then Ulet(p1', u1, body')
else if no_effects a1 then body'
else Usequence(a1, body')
end
| (_, _) -> assert false
-let bind_params params args body =
+let bind_params fpc params args body =
(* Reverse parameters and arguments to preserve right-to-left
evaluation order (PR#2910). *)
- bind_params_rec Tbl.empty (List.rev params) (List.rev args) body
+ bind_params_rec fpc Tbl.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 *)
@@ -532,8 +678,10 @@ let direct_apply fundesc funct ufunct uargs =
if fundesc.fun_closed then uargs else uargs @ [ufunct] in
let app =
match fundesc.fun_inline with
- None -> Udirect_apply(fundesc.fun_label, app_args, Debuginfo.none)
- | Some(params, body) -> bind_params params app_args body in
+ | None ->
+ Udirect_apply(fundesc.fun_label, app_args, Debuginfo.none)
+ | Some(params, body) ->
+ bind_params fundesc.fun_float_const_prop params app_args body in
(* If ufunct can contain side-effects or function definitions,
we must make sure that it is evaluated exactly once.
If the function is not closed, we evaluate ufunct as part of the
@@ -648,14 +796,14 @@ let rec close fenv cenv = function
str (Uconst_block (tag, List.map transl fields))
| Const_float_array sl ->
(* constant float arrays are really immutable *)
- str (Uconst_float_array sl)
+ str (Uconst_float_array (List.map float_of_string sl))
| Const_immstring s ->
str (Uconst_string s)
| Const_base (Const_string (s, _)) ->
(* strings (even literal ones) are mutable! *)
(* of course, the empty string is really immutable *)
str ~shared:false(*(String.length s = 0)*) (Uconst_string s)
- | Const_base(Const_float x) -> str (Uconst_float x)
+ | Const_base(Const_float x) -> str (Uconst_float (float_of_string x))
| Const_base(Const_int32 x) -> str (Uconst_int32 x)
| Const_base(Const_int64 x) -> str (Uconst_int64 x)
| Const_base(Const_nativeint x) -> str (Uconst_nativeint x)
@@ -749,7 +897,7 @@ let rec close fenv cenv = function
(fun (id, pos, approx) sb ->
Tbl.add id (Uoffset(Uvar clos_ident, pos)) sb)
infos Tbl.empty in
- (Ulet(clos_ident, clos, substitute sb ubody),
+ (Ulet(clos_ident, clos, substitute !Clflags.float_const_prop sb ubody),
approx)
end else begin
(* General case: recursive definition of values *)
@@ -757,7 +905,7 @@ let rec close fenv cenv = function
[] -> ([], fenv)
| (id, lam) :: rem ->
let (udefs, fenv_body) = clos_defs rem in
- let (ulam, approx) = close fenv cenv lam in
+ let (ulam, approx) = close_named fenv cenv id lam in
((id, ulam) :: udefs, Tbl.add id approx fenv_body) in
let (udefs, fenv_body) = clos_defs defs in
let (ubody, approx) = close fenv_body cenv body in
@@ -785,7 +933,8 @@ let rec close fenv cenv = function
(Uprim(Praise k, [ulam], Debuginfo.from_raise ev),
Value_unknown)
| Lprim(p, args) ->
- simplif_prim p (close_list_approx fenv cenv args) Debuginfo.none
+ simplif_prim !Clflags.float_const_prop
+ p (close_list_approx fenv cenv args) Debuginfo.none
| Lswitch(arg, sw) ->
let fn fail =
let (uarg, _) = close fenv cenv arg in
@@ -925,7 +1074,8 @@ and close_functions fenv cenv fun_defs =
{fun_label = label;
fun_arity = (if kind = Tupled then -arity else arity);
fun_closed = initially_closed;
- fun_inline = None } in
+ fun_inline = None;
+ fun_float_const_prop = !Clflags.float_const_prop } in
(id, params, body, fundesc)
| (_, _) -> fatal_error "Closure.close_functions")
fun_defs in
@@ -1129,10 +1279,14 @@ let collect_exported_structured_constants a =
in
approx a
+let reset () =
+ global_approx := [||];
+ function_nesting_depth := 0
+
(* The entry point *)
let intro size lam =
- function_nesting_depth := 0;
+ reset ();
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);
diff --git a/asmcomp/closure.mli b/asmcomp/closure.mli
index e7bccbca60..2db6e16336 100644
--- a/asmcomp/closure.mli
+++ b/asmcomp/closure.mli
@@ -13,3 +13,4 @@
(* Introduction of closures, uncurrying, recognition of direct calls *)
val intro: int -> Lambda.lambda -> Clambda.ulambda
+val reset : unit -> unit
diff --git a/asmcomp/cmm.ml b/asmcomp/cmm.ml
index 9a5f3ec6b8..67ee3445fd 100644
--- a/asmcomp/cmm.ml
+++ b/asmcomp/cmm.ml
@@ -85,7 +85,7 @@ type operation =
type expression =
Cconst_int of int
| Cconst_natint of nativeint
- | Cconst_float of string
+ | Cconst_float of float
| Cconst_symbol of string
| Cconst_pointer of int
| Cconst_natpointer of nativeint
@@ -118,8 +118,8 @@ type data_item =
| Cint16 of int
| Cint32 of nativeint
| Cint of nativeint
- | Csingle of string
- | Cdouble of string
+ | Csingle of float
+ | Cdouble of float
| Csymbol_address of string
| Clabel_address of int
| Cstring of string
diff --git a/asmcomp/cmm.mli b/asmcomp/cmm.mli
index be2bd41457..97b8d40971 100644
--- a/asmcomp/cmm.mli
+++ b/asmcomp/cmm.mli
@@ -71,7 +71,7 @@ type operation =
type expression =
Cconst_int of int
| Cconst_natint of nativeint
- | Cconst_float of string
+ | Cconst_float of float
| Cconst_symbol of string
| Cconst_pointer of int
| Cconst_natpointer of nativeint
@@ -104,8 +104,8 @@ type data_item =
| Cint16 of int
| Cint32 of nativeint
| Cint of nativeint
- | Csingle of string
- | Cdouble of string
+ | Csingle of float
+ | Cdouble of float
| Csymbol_address of string
| Clabel_address of int
| Cstring of string
diff --git a/asmcomp/cmmgen.ml b/asmcomp/cmmgen.ml
index 10c4303f82..b68b6a616a 100644
--- a/asmcomp/cmmgen.ml
+++ b/asmcomp/cmmgen.ml
@@ -38,6 +38,8 @@ let bind_nonvar name arg fn =
| Cconst_blockheader _ -> fn arg
| _ -> let id = Ident.create name in Clet(id, arg, fn (Cvar id))
+let caml_black = Nativeint.shift_left (Nativeint.of_int 3) 8 (* cf. byterun/gc.h *)
+
(* Block headers. Meaning of the tag field: see stdlib/obj.ml *)
let floatarray_tag = Cconst_int Obj.double_array_tag
@@ -45,7 +47,12 @@ let floatarray_tag = Cconst_int Obj.double_array_tag
let block_header tag sz =
Nativeint.add (Nativeint.shift_left (Nativeint.of_int sz) 10)
(Nativeint.of_int tag)
-let closure_header sz = block_header Obj.closure_tag sz
+(* Static data corresponding to "value"s must be marked black in case we are
+ in no-naked-pointers mode. See [caml_darken] and the code below that emits
+ structured constants and static module definitions. *)
+let black_block_header tag sz = Nativeint.logor (block_header tag sz) caml_black
+let white_closure_header sz = block_header Obj.closure_tag sz
+let black_closure_header sz = black_block_header Obj.closure_tag sz
let infix_header ofs = block_header Obj.infix_tag ofs
let float_header = block_header Obj.double_tag (size_float / size_addr)
let floatarray_header len =
@@ -59,7 +66,7 @@ let boxedintnat_header = block_header Obj.custom_tag 2
let alloc_block_header tag sz = Cconst_blockheader(block_header tag sz)
let alloc_float_header = Cconst_blockheader(float_header)
let alloc_floatarray_header len = Cconst_blockheader(floatarray_header len)
-let alloc_closure_header sz = Cconst_blockheader(closure_header sz)
+let alloc_closure_header sz = Cconst_blockheader(white_closure_header sz)
let alloc_infix_header ofs = Cconst_blockheader(infix_header ofs)
let alloc_boxedint32_header = Cconst_blockheader(boxedint32_header)
let alloc_boxedint64_header = Cconst_blockheader(boxedint64_header)
@@ -635,7 +642,7 @@ let rec expr_size env = function
RHS_floatblock (List.length args)
| Uprim (Pduprecord ((Record_regular | Record_inlined _), sz), _, _) ->
RHS_block sz
- | Uprim (Pduprecord (Record_exception _, sz), _, _) ->
+ | Uprim (Pduprecord (Record_extension _, sz), _, _) ->
RHS_block (sz + 1)
| Uprim (Pduprecord (Record_float, sz), _, _) ->
RHS_floatblock sz
@@ -1551,6 +1558,8 @@ and transl_prim_1 p arg dbg =
Cop(Cload Double_u,
[if n = 0 then ptr
else Cop(Cadda, [ptr; Cconst_int(n * size_float)])]))
+ | Pint_as_pointer ->
+ Cop(Cadda, [transl arg; Cconst_int (-1)])
(* Exceptions *)
| Praise k ->
Cop(Craise (k, dbg), [transl arg])
@@ -2202,10 +2211,13 @@ let rec transl_all_functions already_translated cont =
(* Emit structured constants *)
-let emit_block header symb cont =
- Cint header :: Cdefine_symbol symb :: cont
-
let rec emit_structured_constant symb cst cont =
+ let emit_block white_header symb cont =
+ (* Headers for structured constants must be marked black in case we
+ are in no-naked-pointers mode. See [caml_darken]. *)
+ let black_header = Nativeint.logor white_header caml_black in
+ Cint black_header :: Cdefine_symbol symb :: cont
+ in
match cst with
| Uconst_float s->
emit_block float_header symb (Cdouble s :: cont)
@@ -2282,7 +2294,7 @@ let emit_constant_closure symb fundecls cont =
Cint(Nativeint.of_int (f2.arity lsl 1 + 1)) ::
Csymbol_address f2.label ::
emit_others (pos + 4) rem in
- Cint(closure_header (fundecls_size fundecls)) ::
+ Cint(black_closure_header (fundecls_size fundecls)) ::
Cdefine_symbol symb ::
if f1.arity = 1 then
Csymbol_address f1.label ::
@@ -2324,10 +2336,18 @@ let compunit size ulam =
fun_dbg = Debuginfo.none }] in
let c2 = transl_all_functions StringSet.empty c1 in
let c3 = emit_all_constants c2 in
- Cdata [Cint(block_header 0 size);
+ let space =
+ (* These words will be registered as roots and as such must contain
+ valid values, in case we are in no-naked-pointers mode. Likewise
+ the block header must be black, below (see [caml_darken]), since
+ the overall record may be referenced. *)
+ Array.to_list
+ (Array.init size (fun _index ->
+ Cint (Nativeint.of_int 1 (* Val_unit *))))
+ in
+ Cdata ([Cint(black_block_header 0 size);
Cglobal_symbol glob;
- Cdefine_symbol glob;
- Cskip(size * size_addr)] :: c3
+ Cdefine_symbol glob] @ space) :: c3
(*
CAMLprim value caml_cache_public_method (value meths, value tag, value *cache)
diff --git a/asmcomp/cmx_format.mli b/asmcomp/cmx_format.mli
index c4e5579699..51aa044083 100644
--- a/asmcomp/cmx_format.mli
+++ b/asmcomp/cmx_format.mli
@@ -26,8 +26,9 @@ type unit_infos =
{ mutable ui_name: string; (* Name of unit implemented *)
mutable ui_symbol: string; (* Prefix for symbols *)
mutable ui_defines: string list; (* Unit and sub-units implemented *)
- mutable ui_imports_cmi: (string * Digest.t) list; (* Interfaces imported *)
- mutable ui_imports_cmx: (string * Digest.t) list; (* Infos imported *)
+ mutable ui_imports_cmi:
+ (string * Digest.t option) list; (* Interfaces imported *)
+ mutable ui_imports_cmx:(string * Digest.t option) list; (* Infos imported *)
mutable ui_approx: Clambda.value_approximation; (* Approx of the structure*)
mutable ui_curry_fun: int list; (* Currying functions needed *)
mutable ui_apply_fun: int list; (* Apply functions needed *)
@@ -49,8 +50,8 @@ type library_infos =
type dynunit = {
dynu_name: string;
dynu_crc: Digest.t;
- dynu_imports_cmi: (string * Digest.t) list;
- dynu_imports_cmx: (string * Digest.t) list;
+ dynu_imports_cmi: (string * Digest.t option) list;
+ dynu_imports_cmx: (string * Digest.t option) list;
dynu_defines: string list;
}
diff --git a/asmcomp/compilenv.ml b/asmcomp/compilenv.ml
index 49a846667d..a313b97202 100644
--- a/asmcomp/compilenv.ml
+++ b/asmcomp/compilenv.ml
@@ -30,9 +30,9 @@ let global_infos_table =
module CstMap =
Map.Make(struct
type t = Clambda.ustructured_constant
- let compare = Pervasives.compare
- (* could use a better version, comparing on the
- first arg of Uconst_ref *)
+ let compare = Clambda.compare_structured_constants
+ (* PR#6442: it is incorrect to use Pervasives.compare on values of type t
+ because it compares "0.0" and "-0.0" equal. *)
end)
type structured_constants =
@@ -118,7 +118,7 @@ let symbol_in_current_unit name =
let read_unit_info filename =
let ic = open_in_bin filename in
try
- let buffer = input_bytes ic (String.length cmx_magic_number) in
+ let buffer = really_input_string ic (String.length cmx_magic_number) in
if buffer <> cmx_magic_number then begin
close_in ic;
raise(Error(Not_a_unit_info filename))
@@ -133,7 +133,7 @@ let read_unit_info filename =
let read_library_info filename =
let ic = open_in_bin filename in
- let buffer = input_bytes ic (String.length cmxa_magic_number) in
+ let buffer = really_input_string ic (String.length cmxa_magic_number) in
if buffer <> cmxa_magic_number then
raise(Error(Not_a_unit_info filename));
let infos = (input_value ic : library_infos) in
@@ -143,9 +143,6 @@ let read_library_info filename =
(* Read and cache info on global identifiers *)
-let cmx_not_found_crc =
- "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
-
let get_global_info global_ident = (
let modname = Ident.name global_ident in
if modname = current_unit.ui_name then
@@ -161,9 +158,9 @@ let get_global_info global_ident = (
let (ui, crc) = read_unit_info filename in
if ui.ui_name <> modname then
raise(Error(Illegal_renaming(modname, ui.ui_name, filename)));
- (Some ui, crc)
+ (Some ui, Some crc)
with Not_found ->
- (None, cmx_not_found_crc) in
+ (None, None) in
current_unit.ui_imports_cmx <-
(modname, crc) :: current_unit.ui_imports_cmx;
Hashtbl.add global_infos_table modname infos;
@@ -231,7 +228,7 @@ let write_unit_info info filename =
close_out oc
let save_unit_info filename =
- current_unit.ui_imports_cmi <- Env.imported_units();
+ current_unit.ui_imports_cmi <- Env.imports();
write_unit_info current_unit filename
diff --git a/asmcomp/compilenv.mli b/asmcomp/compilenv.mli
index b705f4496d..7fae3bade6 100644
--- a/asmcomp/compilenv.mli
+++ b/asmcomp/compilenv.mli
@@ -79,10 +79,6 @@ val cache_unit_info: unit_infos -> unit
honored by [symbol_for_global] and [global_approx]
without looking at the corresponding .cmx file. *)
-val cmx_not_found_crc: Digest.t
- (* Special digest used in the [ui_imports_cmx] list to signal
- that no [.cmx] file was found and used for the imported unit *)
-
val read_library_info: string -> library_infos
type error =
diff --git a/asmcomp/deadcode.ml b/asmcomp/deadcode.ml
new file mode 100644
index 0000000000..cb93c2869d
--- /dev/null
+++ b/asmcomp/deadcode.ml
@@ -0,0 +1,67 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* Dead code elimination: remove pure instructions whose results are
+ not used. *)
+
+open Mach
+
+(* [deadcode i] returns a pair of an optimized instruction [i']
+ and a set of registers live "before" instruction [i]. *)
+
+let rec deadcode i =
+ match i.desc with
+ | Iend | Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _) | Iraise _ ->
+ (i, Reg.add_set_array i.live i.arg)
+ | Iop op ->
+ let (s, before) = deadcode i.next in
+ if Proc.op_is_pure op (* no side effects *)
+ && Reg.disjoint_set_array before i.res (* results are not used after *)
+ && not (Proc.regs_are_volatile i.arg) (* no stack-like hard reg *)
+ && not (Proc.regs_are_volatile i.res) (* is involved *)
+ then begin
+ assert (Array.length i.res > 0); (* sanity check *)
+ (s, before)
+ end else begin
+ ({i with next = s}, Reg.add_set_array i.live i.arg)
+ end
+ | Iifthenelse(test, ifso, ifnot) ->
+ let (ifso', _) = deadcode ifso in
+ let (ifnot', _) = deadcode ifnot in
+ let (s, _) = deadcode i.next in
+ ({i with desc = Iifthenelse(test, ifso', ifnot'); next = s},
+ Reg.add_set_array i.live i.arg)
+ | Iswitch(index, cases) ->
+ let cases' = Array.map (fun c -> fst (deadcode c)) cases in
+ let (s, _) = deadcode i.next in
+ ({i with desc = Iswitch(index, cases'); next = s},
+ Reg.add_set_array i.live i.arg)
+ | Iloop(body) ->
+ let (body', _) = deadcode body in
+ let (s, _) = deadcode i.next in
+ ({i with desc = Iloop body'; next = s}, i.live)
+ | Icatch(nfail, body, handler) ->
+ let (body', _) = deadcode body in
+ let (handler', _) = deadcode handler in
+ let (s, _) = deadcode i.next in
+ ({i with desc = Icatch(nfail, body', handler'); next = s}, i.live)
+ | Iexit nfail ->
+ (i, i.live)
+ | Itrywith(body, handler) ->
+ let (body', _) = deadcode body in
+ let (handler', _) = deadcode handler in
+ let (s, _) = deadcode i.next in
+ ({i with desc = Itrywith(body', handler'); next = s}, i.live)
+
+let fundecl f =
+ let (new_body, _) = deadcode f.fun_body in
+ {f with fun_body = new_body}
diff --git a/asmcomp/deadcode.mli b/asmcomp/deadcode.mli
new file mode 100644
index 0000000000..6aafae0540
--- /dev/null
+++ b/asmcomp/deadcode.mli
@@ -0,0 +1,16 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* Dead code elimination: remove pure instructions whose results are
+ not used. *)
+
+val fundecl: Mach.fundecl -> Mach.fundecl
diff --git a/asmcomp/emitaux.ml b/asmcomp/emitaux.ml
index ccfa977ffa..24a621b339 100644
--- a/asmcomp/emitaux.ml
+++ b/asmcomp/emitaux.ml
@@ -88,16 +88,10 @@ let emit_bytes_directive directive s =
done;
if !pos > 0 then emit_char '\n'
-(* PR#4813: assemblers do strange things with float literals indeed,
- so we convert to IEEE representation ourselves and emit float
- literals as 32- or 64-bit integers. *)
-
-let emit_float64_directive directive f =
- let x = Int64.bits_of_float (float_of_string f) in
+let emit_float64_directive directive x =
emit_printf "\t%s\t0x%Lx\n" directive x
-let emit_float64_split_directive directive f =
- let x = Int64.bits_of_float (float_of_string f) in
+let emit_float64_split_directive directive x =
let lo = Int64.logand x 0xFFFF_FFFFL
and hi = Int64.shift_right_logical x 32 in
emit_printf "\t%s\t0x%Lx, 0x%Lx\n"
@@ -105,8 +99,7 @@ let emit_float64_split_directive directive f =
(if Arch.big_endian then hi else lo)
(if Arch.big_endian then lo else hi)
-let emit_float32_directive directive f =
- let x = Int32.bits_of_float (float_of_string f) in
+let emit_float32_directive directive x =
emit_printf "\t%s\t0x%lx\n" directive x
(* Record live pointers at call points *)
@@ -239,3 +232,7 @@ let emit_debug_info dbg =
emit_int file_num; emit_char '\t';
emit_int line; emit_char '\n'
end
+
+let reset () =
+ reset_debug_info ();
+ frame_descriptors := []
diff --git a/asmcomp/emitaux.mli b/asmcomp/emitaux.mli
index cc479d8ccf..486a5839ce 100644
--- a/asmcomp/emitaux.mli
+++ b/asmcomp/emitaux.mli
@@ -23,10 +23,11 @@ val emit_char: char -> unit
val emit_string_literal: string -> unit
val emit_string_directive: string -> string -> unit
val emit_bytes_directive: string -> string -> unit
-val emit_float64_directive: string -> string -> unit
-val emit_float64_split_directive: string -> string -> unit
-val emit_float32_directive: string -> string -> unit
+val emit_float64_directive: string -> int64 -> unit
+val emit_float64_split_directive: string -> int64 -> unit
+val emit_float32_directive: string -> int32 -> unit
+val reset : unit -> unit
val reset_debug_info: unit -> unit
val emit_debug_info: Debuginfo.t -> unit
diff --git a/asmcomp/i386/CSE.ml b/asmcomp/i386/CSE.ml
new file mode 100644
index 0000000000..3ce4567024
--- /dev/null
+++ b/asmcomp/i386/CSE.ml
@@ -0,0 +1,48 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* CSE for the i386 *)
+
+open Cmm
+open Arch
+open Mach
+open CSEgen
+
+class cse = object (self)
+
+inherit cse_generic as super
+
+method! class_of_operation op =
+ match op with
+ (* Operations that affect the floating-point stack cannot be factored *)
+ | Iconst_float _ | Inegf | Iabsf | Iaddf | Isubf | Imulf | Idivf
+ | Iintoffloat | Ifloatofint
+ | Iload((Single | Double | Double_u), _) -> Op_other
+ (* Specific ops *)
+ | Ispecific(Ilea _) -> Op_pure
+ | Ispecific(Istore_int(_, _, is_asg)) -> Op_store is_asg
+ | Ispecific(Istore_symbol(_, _, is_asg)) -> Op_store is_asg
+ | Ispecific(Ioffset_loc(_, _)) -> Op_store true
+ | Ispecific _ -> Op_other
+ | _ -> super#class_of_operation op
+
+method! is_cheap_operation op =
+ match op with
+ | Iconst_int _ | Iconst_blockheader _ -> true
+ | Iconst_symbol _ -> true
+ | _ -> false
+
+end
+
+let fundecl f =
+ (new cse)#fundecl f
+
diff --git a/asmcomp/i386/arch.ml b/asmcomp/i386/arch.ml
index d2f9fd61a8..25e6edb68d 100644
--- a/asmcomp/i386/arch.ml
+++ b/asmcomp/i386/arch.ml
@@ -31,8 +31,8 @@ type addressing_mode =
type specific_operation =
Ilea of addressing_mode (* Lea gives scaled adds *)
- | Istore_int of nativeint * addressing_mode (* Store an integer constant *)
- | Istore_symbol of string * addressing_mode (* Store a symbol *)
+ | Istore_int of nativeint * addressing_mode * bool (* Store an integer constant *)
+ | Istore_symbol of string * addressing_mode * bool (* Store a symbol *)
| Ioffset_loc of int * addressing_mode (* Add a constant to a location *)
| Ipush (* Push regs on stack *)
| Ipush_int of nativeint (* Push an integer constant *)
@@ -105,11 +105,14 @@ let print_addressing printreg addr ppf arg =
let print_specific_operation printreg op ppf arg =
match op with
| Ilea addr -> print_addressing printreg addr ppf arg
- | Istore_int(n, addr) ->
- fprintf ppf "[%a] := %s" (print_addressing printreg addr) arg
- (Nativeint.to_string n)
- | Istore_symbol(lbl, addr) ->
- fprintf ppf "[%a] := \"%s\"" (print_addressing printreg addr) arg lbl
+ | Istore_int(n, addr, is_assign) ->
+ fprintf ppf "[%a] := %nd %s"
+ (print_addressing printreg addr) arg n
+ (if is_assign then "(assign)" else "(init)")
+ | Istore_symbol(lbl, addr, is_assign) ->
+ fprintf ppf "[%a] := \"%s\" %s"
+ (print_addressing printreg addr) arg lbl
+ (if is_assign then "(assign)" else "(init)")
| Ioffset_loc(n, addr) ->
fprintf ppf "[%a] +:= %i" (print_addressing printreg addr) arg n
| Ipush ->
@@ -152,5 +155,7 @@ let print_specific_operation printreg op ppf arg =
let stack_alignment =
match Config.system with
- | "macosx" -> 16
- | _ -> 4
+ | "win32" -> 4 (* MSVC *)
+ | _ -> 16
+(* PR#6038: GCC and Clang seem to require 16-byte alignment nowadays,
+ even if only MacOS X's ABI formally requires it *)
diff --git a/asmcomp/i386/emit.mlp b/asmcomp/i386/emit.mlp
index 2b90d37f64..98df5f958b 100644
--- a/asmcomp/i386/emit.mlp
+++ b/asmcomp/i386/emit.mlp
@@ -412,15 +412,16 @@ let emit_floatspecial = function
(* Floating-point constants *)
-let float_constants = ref ([] : (string * int) list)
+let float_constants = ref ([] : (int64 * int) list)
let add_float_constant cst =
+ let repr = Int64.bits_of_float cst in
try
- List.assoc cst !float_constants
+ List.assoc repr !float_constants
with
Not_found ->
let lbl = new_label() in
- float_constants := (cst, lbl) :: !float_constants;
+ float_constants := (repr, lbl) :: !float_constants;
lbl
let emit_float_constant (cst, lbl) =
@@ -465,8 +466,8 @@ let emit_instr fallthrough i =
| _ -> ` movl $0, {emit_reg i.res.(0)}\n`
end else
` movl ${emit_nativeint n}, {emit_reg i.res.(0)}\n`
- | Lop(Iconst_float s) ->
- begin match Int64.bits_of_float (float_of_string s) with
+ | Lop(Iconst_float f) ->
+ begin match Int64.bits_of_float f with
| 0x0000_0000_0000_0000L -> (* +0.0 *)
` fldz\n`
| 0x8000_0000_0000_0000L -> (* -0.0 *)
@@ -476,7 +477,7 @@ let emit_instr fallthrough i =
| 0xBFF0_0000_0000_0000L -> (* -1.0 *)
` fld1\n fchs\n`
| _ ->
- let lbl = add_float_constant s in
+ let lbl = add_float_constant f in
` fldl {emit_label lbl}\n`
end
| Lop(Iconst_symbol s) ->
@@ -543,7 +544,7 @@ let emit_instr fallthrough i =
| Double | Double_u ->
` fldl {emit_addressing addr i.arg 0}\n`
end
- | Lop(Istore(chunk, addr)) ->
+ | Lop(Istore(chunk, addr, _)) ->
begin match chunk with
| Word | Thirtytwo_signed | Thirtytwo_unsigned ->
` movl {emit_reg i.arg.(0)}, {emit_addressing addr i.arg 1}\n`
@@ -683,9 +684,9 @@ let emit_instr fallthrough i =
stack_offset := !stack_offset + 8
| Lop(Ispecific(Ilea addr)) ->
` lea {emit_addressing addr i.arg 0}, {emit_reg i.res.(0)}\n`
- | Lop(Ispecific(Istore_int(n, addr))) ->
+ | Lop(Ispecific(Istore_int(n, addr, _))) ->
` movl ${emit_nativeint n}, {emit_addressing addr i.arg 0}\n`
- | Lop(Ispecific(Istore_symbol(s, addr))) ->
+ | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
` movl ${emit_symbol s}, {emit_addressing addr i.arg 0}\n`
| Lop(Ispecific(Ioffset_loc(n, addr))) ->
` addl ${emit_int n}, {emit_addressing addr i.arg 0}\n`
@@ -960,9 +961,9 @@ let emit_item = function
| Cint n ->
` .long {emit_nativeint n}\n`
| Csingle f ->
- emit_float32_directive ".long" f
+ emit_float32_directive ".long" (Int32.bits_of_float f)
| Cdouble f ->
- emit_float64_split_directive ".long" f
+ emit_float64_split_directive ".long" (Int64.bits_of_float f)
| Csymbol_address s ->
` .long {emit_symbol s}\n`
| Clabel_address lbl ->
diff --git a/asmcomp/i386/emit_nt.mlp b/asmcomp/i386/emit_nt.mlp
index 495a29aecc..ef5205ef8f 100644
--- a/asmcomp/i386/emit_nt.mlp
+++ b/asmcomp/i386/emit_nt.mlp
@@ -62,7 +62,10 @@ let add_used_symbol s =
let emit_symbol s =
emit_string "_"; Emitaux.emit_symbol '$' s
+(* Output a 32 or 64 bit integer in hex *)
+
let emit_int32 n = emit_printf "0%lxh" n
+let emit_int64 n = emit_printf "0%Lxh" n
(* Output a label *)
@@ -361,36 +364,20 @@ let emit_floatspecial = function
(* Floating-point constants *)
-let float_constants = ref ([] : (string * int) list)
+let float_constants = ref ([] : (int64 * int) list)
let add_float_constant cst =
+ let repr = Int64.bits_of_float cst in
try
- List.assoc cst !float_constants
+ List.assoc repr !float_constants
with
Not_found ->
let lbl = new_label() in
- float_constants := (cst, lbl) :: !float_constants;
+ float_constants := (repr, lbl) :: !float_constants;
lbl
-let emit_float s =
- (* MASM doesn't like floating-point constants such as 2e9.
- Turn them into 2.0e9. *)
- let pos_e = ref (-1) and pos_dot = ref (-1) in
- for i = 0 to String.length s - 1 do
- match s.[i] with
- 'e'|'E' -> pos_e := i
- | '.' -> pos_dot := i
- | _ -> ()
- done;
- if !pos_dot < 0 && !pos_e >= 0 then begin
- emit_string (String.sub s 0 !pos_e);
- emit_string ".0";
- emit_string (String.sub s !pos_e (String.length s - !pos_e))
- end else
- emit_string s
-
let emit_float_constant (cst, lbl) =
- `{emit_label lbl} REAL8 {emit_float cst}\n`
+ `{emit_label lbl} QWORD {emit_int64 cst}\n`
(* Output the assembly code for an instruction *)
@@ -426,8 +413,8 @@ let emit_instr i =
| _ -> ` mov {emit_reg i.res.(0)}, 0\n`
end else
` mov {emit_reg i.res.(0)}, {emit_nativeint n}\n`
- | Lop(Iconst_float s) ->
- begin match Int64.bits_of_float (float_of_string s) with
+ | Lop(Iconst_float f) ->
+ begin match Int64.bits_of_float f with
| 0x0000_0000_0000_0000L -> (* +0.0 *)
` fldz\n`
| 0x8000_0000_0000_0000L -> (* -0.0 *)
@@ -437,7 +424,7 @@ let emit_instr i =
| 0xBFF0_0000_0000_0000L -> (* -1.0 *)
` fld1\n fchs\n`
| _ ->
- let lbl = add_float_constant s in
+ let lbl = add_float_constant f in
` fld {emit_label lbl}\n`
end
| Lop(Iconst_symbol s) ->
@@ -493,7 +480,7 @@ let emit_instr i =
| Double | Double_u ->
` fld REAL8 PTR {emit_addressing addr i.arg 0}\n`
end
- | Lop(Istore(chunk, addr)) ->
+ | Lop(Istore(chunk, addr, _)) ->
begin match chunk with
| Word | Thirtytwo_signed | Thirtytwo_unsigned ->
` mov DWORD PTR {emit_addressing addr i.arg 1}, {emit_reg i.arg.(0)}\n`
@@ -631,9 +618,9 @@ let emit_instr i =
stack_offset := !stack_offset + 8
| Lop(Ispecific(Ilea addr)) ->
` lea {emit_reg i.res.(0)}, DWORD PTR {emit_addressing addr i.arg 0}\n`
- | Lop(Ispecific(Istore_int(n, addr))) ->
+ | Lop(Ispecific(Istore_int(n, addr, _))) ->
` mov DWORD PTR {emit_addressing addr i.arg 0},{emit_nativeint n}\n`
- | Lop(Ispecific(Istore_symbol(s, addr))) ->
+ | Lop(Ispecific(Istore_symbol(s, addr, _))) ->
add_used_symbol s ;
` mov DWORD PTR {emit_addressing addr i.arg 0},OFFSET {emit_symbol s}\n`
| Lop(Ispecific(Ioffset_loc(n, addr))) ->
@@ -816,9 +803,9 @@ let emit_item = function
| Cint32 n ->
` DWORD {emit_nativeint n}\n`
| Csingle f ->
- ` REAL4 {emit_float f}\n`
+ ` DWORD {emit_int32 (Int32.bits_of_float f)}\n`
| Cdouble f ->
- ` REAL8 {emit_float f}\n`
+ ` QWORD {emit_int64 (Int64.bits_of_float f)}\n`
| Csymbol_address s ->
add_used_symbol s ;
` DWORD {emit_symbol s}\n`
diff --git a/asmcomp/i386/proc.ml b/asmcomp/i386/proc.ml
index d80d182088..8bbd42c158 100644
--- a/asmcomp/i386/proc.ml
+++ b/asmcomp/i386/proc.ml
@@ -154,6 +154,21 @@ let loc_external_results res =
let loc_exn_bucket = eax
+(* Volatile registers: the x87 top of FP stack is *)
+
+let reg_is_volatile = function
+ | { typ = Float; loc = Reg _ } -> true
+ | _ -> false
+
+let regs_are_volatile rs =
+ try
+ for i = 0 to Array.length rs - 1 do
+ if reg_is_volatile rs.(i) then raise Exit
+ done;
+ false
+ with Exit ->
+ true
+
(* Registers destroyed by operations *)
let destroyed_at_c_call = (* ebx, esi, edi, ebp preserved *)
@@ -182,6 +197,17 @@ let max_register_pressure = function
Iintoffloat -> [| 6; max_int |]
| _ -> [|7; max_int |]
+(* Pure operations (without any side effect besides updating their result
+ registers). *)
+
+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 _ -> false
+ | _ -> true
+
(* Layout of the stack frame *)
let num_stack_slots = [| 0; 0 |]
diff --git a/asmcomp/i386/selection.ml b/asmcomp/i386/selection.ml
index d86f1b2823..10d2d40e37 100644
--- a/asmcomp/i386/selection.ml
+++ b/asmcomp/i386/selection.ml
@@ -135,7 +135,7 @@ let pseudoregs_for_operation op arg res =
(* For storing a byte, the argument must be in eax...edx.
(But for a short, any reg will do!)
Keep it simple, just force the argument to be in edx. *)
- | Istore((Byte_unsigned | Byte_signed), addr) ->
+ | Istore((Byte_unsigned | Byte_signed), addr, _) ->
let newarg = Array.copy arg in
newarg.(0) <- edx;
(newarg, res, false)
@@ -178,20 +178,20 @@ method select_addressing chunk exp =
| (Ascaledadd(e1, e2, scale), d) ->
(Iindexed2scaled(scale, d), Ctuple[e1; e2])
-method! select_store addr exp =
+method! select_store is_assign addr exp =
match exp with
Cconst_int n ->
- (Ispecific(Istore_int(Nativeint.of_int n, addr)), Ctuple [])
+ (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
| (Cconst_natint n | Cconst_blockheader n) ->
- (Ispecific(Istore_int(n, addr)), Ctuple [])
+ (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
| Cconst_pointer n ->
- (Ispecific(Istore_int(Nativeint.of_int n, addr)), Ctuple [])
+ (Ispecific(Istore_int(Nativeint.of_int n, addr, is_assign)), Ctuple [])
| Cconst_natpointer n ->
- (Ispecific(Istore_int(n, addr)), Ctuple [])
+ (Ispecific(Istore_int(n, addr, is_assign)), Ctuple [])
| Cconst_symbol s ->
- (Ispecific(Istore_symbol(s, addr)), Ctuple [])
+ (Ispecific(Istore_symbol(s, addr, is_assign)), Ctuple [])
| _ ->
- super#select_store addr exp
+ super#select_store is_assign addr exp
method! select_operation op args =
match op with
diff --git a/asmcomp/linearize.ml b/asmcomp/linearize.ml
index ebe590c56c..48dde690c4 100644
--- a/asmcomp/linearize.ml
+++ b/asmcomp/linearize.ml
@@ -126,9 +126,9 @@ let rec discard_dead_code n =
match n.desc with
Lend -> n
| Llabel _ -> n
-(* Do not discard Lpoptrap or Istackoffset instructions,
+(* Do not discard Lpoptrap/Lpushtrap or Istackoffset instructions,
as this may cause a stack imbalance later during assembler generation. *)
- | Lpoptrap -> n
+ | Lpoptrap | Lpushtrap -> n
| Lop(Istackoffset _) -> n
| _ -> discard_dead_code n.next
@@ -148,20 +148,30 @@ let add_branch lbl n =
else
discard_dead_code n
-(* Current labels for exit handler *)
+let try_depth = ref 0
+
+(* Association list: exit handler -> (handler label, try-nesting factor) *)
let exit_label = ref []
-let find_exit_label k =
+let find_exit_label_try_depth k =
try
List.assoc k !exit_label
with
| Not_found -> Misc.fatal_error "Linearize.find_exit_label"
+let find_exit_label k =
+ let (label, t) = find_exit_label_try_depth k in
+ assert(t = !try_depth);
+ label
+
let is_next_catch n = match !exit_label with
-| (n0,_)::_ when n0=n -> true
+| (n0,(_,t))::_ when n0=n && t = !try_depth -> true
| _ -> false
+let local_exit k =
+ snd (find_exit_label_try_depth k) = !try_depth
+
(* Linearize an instruction [i]: add it in front of the continuation [n] *)
let rec linear i n =
@@ -187,15 +197,15 @@ let rec linear i n =
| _, Iend, Lbranch lbl ->
copy_instr (Lcondbranch(invert_test test, lbl)) i (linear ifso n1)
| Iexit nfail1, Iexit nfail2, _
- when is_next_catch nfail1 ->
+ when is_next_catch nfail1 && local_exit nfail2 ->
let lbl2 = find_exit_label nfail2 in
copy_instr
(Lcondbranch (invert_test test, lbl2)) i (linear ifso n1)
- | Iexit nfail, _, _ ->
+ | Iexit nfail, _, _ when local_exit nfail ->
let n2 = linear ifnot n1
and lbl = find_exit_label nfail in
copy_instr (Lcondbranch(test, lbl)) i n2
- | _, Iexit nfail, _ ->
+ | _, Iexit nfail, _ when local_exit nfail ->
let n2 = linear ifso n1 in
let lbl = find_exit_label nfail in
copy_instr (Lcondbranch(invert_test test, lbl)) i n2
@@ -242,24 +252,44 @@ let rec linear i n =
| Icatch(io, body, handler) ->
let (lbl_end, n1) = get_label(linear i.Mach.next n) in
let (lbl_handler, n2) = get_label(linear handler n1) in
- exit_label := (io, lbl_handler) :: !exit_label ;
+ exit_label := (io, (lbl_handler, !try_depth)) :: !exit_label ;
let n3 = linear body (add_branch lbl_end n2) in
exit_label := List.tl !exit_label;
n3
| Iexit nfail ->
- let n1 = linear i.Mach.next n in
- let lbl = find_exit_label nfail in
- add_branch lbl n1
+ let lbl, t = find_exit_label_try_depth nfail in
+ (* We need to re-insert dummy pushtrap (which won't be executed),
+ so as to preserve stack offset during assembler generation.
+ It would make sense to have a special pseudo-instruction
+ only to inform the later pass about this stack offset
+ (corresponding to N traps).
+ *)
+ let rec loop i tt =
+ if t = tt then i
+ else loop (cons_instr Lpushtrap i) (tt - 1)
+ in
+ let n1 = loop (linear i.Mach.next n) !try_depth in
+ let rec loop i tt =
+ if t = tt then i
+ else loop (cons_instr Lpoptrap i) (tt - 1)
+ in
+ loop (add_branch lbl n1) !try_depth
| Itrywith(body, handler) ->
let (lbl_join, n1) = get_label (linear i.Mach.next n) in
+ incr try_depth;
let (lbl_body, n2) =
get_label (cons_instr Lpushtrap
(linear body (cons_instr Lpoptrap n1))) in
+ decr try_depth;
cons_instr (Lsetuptrap lbl_body)
(linear handler (add_branch lbl_join n2))
| Iraise k ->
copy_instr (Lraise k) i (discard_dead_code n)
+let reset () =
+ label_counter := 99;
+ exit_label := []
+
let fundecl f =
{ fun_name = f.Mach.fun_name;
fun_body = linear f.Mach.fun_body end_instr;
diff --git a/asmcomp/linearize.mli b/asmcomp/linearize.mli
index 22987e5ba1..2996a29bf2 100644
--- a/asmcomp/linearize.mli
+++ b/asmcomp/linearize.mli
@@ -50,4 +50,5 @@ type fundecl =
fun_fast: bool;
fun_dbg : Debuginfo.t }
+val reset : unit -> unit
val fundecl: Mach.fundecl -> fundecl
diff --git a/asmcomp/liveness.ml b/asmcomp/liveness.ml
index 434d506558..2ef322ef3e 100644
--- a/asmcomp/liveness.ml
+++ b/asmcomp/liveness.ml
@@ -16,13 +16,13 @@
open Mach
let live_at_exit = ref []
+
let find_live_at_exit k =
try
List.assoc k !live_at_exit
with
- | Not_found -> Misc.fatal_error "Spill.find_live_at_exit"
+ | Not_found -> Misc.fatal_error "Liveness.find_live_at_exit"
-let live_at_break = ref Reg.Set.empty
let live_at_raise = ref Reg.Set.empty
let rec live i finally =
@@ -37,8 +37,34 @@ let rec live i finally =
i.live <- finally;
finally
| Ireturn | Iop(Itailcall_ind) | Iop(Itailcall_imm _) ->
- (* i.live remains empty since no regs are live across *)
+ i.live <- Reg.Set.empty; (* no regs are live across *)
Reg.set_of_array i.arg
+ | Iop op ->
+ let after = live i.next finally in
+ if Proc.op_is_pure op (* no side effects *)
+ && Reg.disjoint_set_array after i.res (* results are not used after *)
+ && not (Proc.regs_are_volatile i.arg) (* no stack-like hard reg *)
+ && not (Proc.regs_are_volatile i.res) (* is involved *)
+ then begin
+ (* This operation is dead code. Ignore its arguments. *)
+ i.live <- after;
+ after
+ end else begin
+ let across_after = Reg.diff_set_array after i.res in
+ let across =
+ match op with
+ | Icall_ind | Icall_imm _ | Iextcall _
+ | Iintop Icheckbound | Iintop_imm(Icheckbound, _) ->
+ (* The function call may raise an exception, branching to the
+ nearest enclosing try ... with. Similarly for bounds checks.
+ Hence, everything that must be live at the beginning of
+ the exception handler must also be live across this instr. *)
+ Reg.Set.union across_after !live_at_raise
+ | _ ->
+ across_after in
+ i.live <- across;
+ Reg.add_set_array across i.arg
+ end
| Iifthenelse(test, ifso, ifnot) ->
let at_join = live i.next finally in
let at_fork = Reg.Set.union (live ifso at_join) (live ifnot at_join) in
@@ -90,23 +116,12 @@ let rec live i finally =
i.live <- before_body;
before_body
| Iraise _ ->
- (* i.live remains empty since no regs are live across *)
+ i.live <- !live_at_raise;
Reg.add_set_array !live_at_raise i.arg
- | _ ->
- let across_after = Reg.diff_set_array (live i.next finally) i.res in
- let across =
- match i.desc with
- Iop Icall_ind | Iop(Icall_imm _) | Iop(Iextcall _)
- | Iop(Iintop Icheckbound) | Iop(Iintop_imm(Icheckbound, _)) ->
- (* The function call may raise an exception, branching to the
- nearest enclosing try ... with. Similarly for bounds checks.
- Hence, everything that must be live at the beginning of
- the exception handler must also be live across this instr. *)
- Reg.Set.union across_after !live_at_raise
- | _ ->
- across_after in
- i.live <- across;
- Reg.add_set_array across i.arg
+
+let reset () =
+ live_at_raise := Reg.Set.empty;
+ live_at_exit := []
let fundecl ppf f =
let initially_live = live f.fun_body Reg.Set.empty in
diff --git a/asmcomp/liveness.mli b/asmcomp/liveness.mli
index b52ec5a2b8..ed2f1a8aeb 100644
--- a/asmcomp/liveness.mli
+++ b/asmcomp/liveness.mli
@@ -15,4 +15,5 @@
open Format
+val reset : unit -> unit
val fundecl: formatter -> Mach.fundecl -> unit
diff --git a/asmcomp/mach.ml b/asmcomp/mach.ml
index a11910ec73..3a7174763a 100644
--- a/asmcomp/mach.ml
+++ b/asmcomp/mach.ml
@@ -36,7 +36,7 @@ type operation =
| Ispill
| Ireload
| Iconst_int of nativeint
- | Iconst_float of string
+ | Iconst_float of float
| Iconst_symbol of string
| Iconst_blockheader of nativeint
| Icall_ind
@@ -46,7 +46,7 @@ type operation =
| Iextcall of string * bool
| Istackoffset of int
| Iload of Cmm.memory_chunk * Arch.addressing_mode
- | Istore of Cmm.memory_chunk * Arch.addressing_mode
+ | Istore of Cmm.memory_chunk * Arch.addressing_mode * bool
| Ialloc of int
| Iintop of integer_operation
| Iintop_imm of integer_operation * int
diff --git a/asmcomp/mach.mli b/asmcomp/mach.mli
index 000c3cf9f1..618e5e4ce7 100644
--- a/asmcomp/mach.mli
+++ b/asmcomp/mach.mli
@@ -36,17 +36,18 @@ type operation =
| Ispill
| Ireload
| Iconst_int of nativeint
- | Iconst_float of string
+ | Iconst_float of float
| Iconst_symbol of string
| Iconst_blockheader of nativeint
| Icall_ind
| Icall_imm of string
| Itailcall_ind
| Itailcall_imm of string
- | Iextcall of string * bool
+ | Iextcall of string * bool (* false = noalloc, true = alloc *)
| Istackoffset of int
| Iload of Cmm.memory_chunk * Arch.addressing_mode
- | Istore of Cmm.memory_chunk * Arch.addressing_mode
+ | Istore of Cmm.memory_chunk * Arch.addressing_mode * bool
+ (* false = initialization, true = assignment *)
| Ialloc of int
| Iintop of integer_operation
| Iintop_imm of integer_operation * int
diff --git a/asmcomp/power/CSE.ml b/asmcomp/power/CSE.ml
new file mode 100644
index 0000000000..50fefa5e35
--- /dev/null
+++ b/asmcomp/power/CSE.ml
@@ -0,0 +1,38 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* CSE for the PowerPC *)
+
+open Arch
+open Mach
+open CSEgen
+
+class cse = object (self)
+
+inherit cse_generic as super
+
+method! class_of_operation op =
+ match op with
+ | Ispecific(Imultaddf | Imultsubf) -> Op_pure
+ | Ispecific(Ialloc_far _) -> Op_other
+ | _ -> super#class_of_operation op
+
+method! is_cheap_operation op =
+ match op with
+ | Iconst_int n | Iconst_blockheader n -> n <= 32767n && n >= -32768n
+ | _ -> false
+
+end
+
+let fundecl f =
+ (new cse)#fundecl f
+
diff --git a/asmcomp/power/emit.mlp b/asmcomp/power/emit.mlp
index f6ee1a2321..0a26ed1479 100644
--- a/asmcomp/power/emit.mlp
+++ b/asmcomp/power/emit.mlp
@@ -229,7 +229,7 @@ let record_frame live dbg =
(* Record floating-point and large integer literals *)
-let float_literals = ref ([] : (string * int) list)
+let float_literals = ref ([] : (int64 * int) list)
let int_literals = ref ([] : (nativeint * int) list)
(* Record external C functions to be called in a position-independent way
@@ -333,7 +333,7 @@ let instr_size = function
if chunk = Byte_signed
then load_store_size addr + 1
else load_store_size addr
- | Lop(Istore(chunk, addr)) -> load_store_size addr
+ | Lop(Istore(chunk, addr, _)) -> load_store_size addr
| Lop(Ialloc n) -> 4
| Lop(Ispecific(Ialloc_far n)) -> 5
| Lop(Iintop Imod) -> 3
@@ -466,9 +466,9 @@ let rec emit_instr i dslot =
` addis {emit_gpr 11}, 0, {emit_upper emit_label lbl}\n`;
` {emit_string lg} {emit_reg i.res.(0)}, {emit_lower emit_label lbl}({emit_gpr 11})\n`
end
- | Lop(Iconst_float s) ->
+ | Lop(Iconst_float f) ->
let lbl = new_label() in
- float_literals := (s, lbl) :: !float_literals;
+ float_literals := (Int64.bits_of_float f, lbl) :: !float_literals;
` addis {emit_gpr 11}, 0, {emit_upper emit_label lbl}\n`;
` lfd {emit_reg i.res.(0)}, {emit_lower emit_label lbl}({emit_gpr 11})\n`
| Lop(Iconst_symbol s) ->
@@ -548,7 +548,7 @@ let rec emit_instr i dslot =
emit_load_store loadinstr addr i.arg 0 i.res.(0);
if chunk = Byte_signed then
` extsb {emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
- | Lop(Istore(chunk, addr)) ->
+ | Lop(Istore(chunk, addr, _)) ->
let storeinstr =
match chunk with
Byte_unsigned | Byte_signed -> "stb"
@@ -628,8 +628,7 @@ let rec emit_instr i dslot =
` fcfid {emit_reg i.res.(0)}, {emit_reg i.res.(0)}\n`
end else begin
let lbl = new_label() in
- float_literals := ("4.503601774854144e15", lbl) :: !float_literals;
- (* That float above represents 0x4330000080000000 *)
+ float_literals := (0x4330000080000000L, lbl) :: !float_literals;
` addis {emit_gpr 11}, 0, {emit_upper emit_label lbl}\n`;
` lfd {emit_fpr 0}, {emit_lower emit_label lbl}({emit_gpr 11})\n`;
` lis {emit_gpr 0}, 0x4330\n`;
@@ -899,11 +898,11 @@ let emit_item = function
| Cint n ->
` {emit_string datag} {emit_nativeint n}\n`
| Csingle f ->
- emit_float32_directive ".long" f
+ emit_float32_directive ".long" (Int32.bits_of_float f)
| Cdouble f ->
if ppc64
- then emit_float64_directive ".quad" f
- else emit_float64_split_directive ".long" f
+ then emit_float64_directive ".quad" (Int64.bits_of_float f)
+ else emit_float64_split_directive ".long" (Int64.bits_of_float f)
| Csymbol_address s ->
` {emit_string datag} {emit_symbol s}\n`
| Clabel_address lbl ->
diff --git a/asmcomp/power/proc.ml b/asmcomp/power/proc.ml
index 203e8a9ef4..bafa8a4c5f 100644
--- a/asmcomp/power/proc.ml
+++ b/asmcomp/power/proc.ml
@@ -200,6 +200,10 @@ let loc_external_results res =
let loc_exn_bucket = phys_reg 0
+(* Volatile registers: none *)
+
+let regs_are_volatile rs = false
+
(* Registers destroyed by operations *)
let destroyed_at_c_call =
@@ -224,6 +228,17 @@ let max_register_pressure = function
Iextcall(_, _) -> [| 15; 18 |]
| _ -> [| 23; 30 |]
+(* Pure operations (without any side effect besides updating their result
+ registers). *)
+
+let op_is_pure = function
+ | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+ | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
+ | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) -> false
+ | Ispecific(Imultaddf | Imultsubf) -> true
+ | Ispecific _ -> false
+ | _ -> true
+
(* Layout of the stack *)
let num_stack_slots = [| 0; 0 |]
diff --git a/asmcomp/power/scheduling.ml b/asmcomp/power/scheduling.ml
index 6e594f0283..7adaa2eed3 100644
--- a/asmcomp/power/scheduling.ml
+++ b/asmcomp/power/scheduling.ml
@@ -44,7 +44,7 @@ method reload_retaddr_latency = 12
method oper_issue_cycles = function
Iconst_float _ | Iconst_symbol _ -> 2
| Iload(_, Ibased(_, _)) -> 2
- | Istore(_, Ibased(_, _)) -> 2
+ | Istore(_, Ibased(_, _), _) -> 2
| Ialloc _ -> 4
| Iintop(Imod) -> 40 (* assuming full stall *)
| Iintop(Icomp _) -> 4
diff --git a/asmcomp/printclambda.ml b/asmcomp/printclambda.ml
index f4e3b4d93f..b28d749e24 100644
--- a/asmcomp/printclambda.ml
+++ b/asmcomp/printclambda.ml
@@ -16,17 +16,20 @@ open Asttypes
open Clambda
let rec structured_constant ppf = function
- | Uconst_float x -> fprintf ppf "%s" x
- | Uconst_int32 x -> fprintf ppf "%ld" x
- | Uconst_int64 x -> fprintf ppf "%Ld" x
- | Uconst_nativeint x -> fprintf ppf "%nd" x
+ | Uconst_float x -> fprintf ppf "%F" x
+ | Uconst_int32 x -> fprintf ppf "%ldl" x
+ | Uconst_int64 x -> fprintf ppf "%LdL" x
+ | Uconst_nativeint x -> fprintf ppf "%ndn" x
| Uconst_block (tag, l) ->
fprintf ppf "block(%i" tag;
List.iter (fun u -> fprintf ppf ",%a" uconstant u) l;
fprintf ppf ")"
- | Uconst_float_array sl ->
- fprintf ppf "floatarray(%s)"
- (String.concat "," sl)
+ | Uconst_float_array [] ->
+ fprintf ppf "floatarray()"
+ | Uconst_float_array (f1 :: fl) ->
+ fprintf ppf "floatarray(%F" f1;
+ List.iter (fun f -> fprintf ppf ",%F" f) fl;
+ fprintf ppf ")"
| Uconst_string s -> fprintf ppf "%S" s
and uconstant ppf = function
diff --git a/asmcomp/printcmm.ml b/asmcomp/printcmm.ml
index 008081fb47..89c8582aef 100644
--- a/asmcomp/printcmm.ml
+++ b/asmcomp/printcmm.ml
@@ -89,7 +89,7 @@ let rec expr ppf = function
| Cconst_int n -> fprintf ppf "%i" n
| Cconst_natint n | Cconst_blockheader n ->
fprintf ppf "%s" (Nativeint.to_string n)
- | Cconst_float s -> fprintf ppf "%s" s
+ | Cconst_float n -> fprintf ppf "%F" n
| Cconst_symbol s -> fprintf ppf "\"%s\"" s
| Cconst_pointer n -> fprintf ppf "%ia" n
| Cconst_natpointer n -> fprintf ppf "%sa" (Nativeint.to_string n)
@@ -188,8 +188,8 @@ let data_item ppf = function
| Cint16 n -> fprintf ppf "int16 %i" n
| Cint32 n -> fprintf ppf "int32 %s" (Nativeint.to_string n)
| Cint n -> fprintf ppf "int %s" (Nativeint.to_string n)
- | Csingle f -> fprintf ppf "single %s" f
- | Cdouble f -> fprintf ppf "double %s" f
+ | Csingle f -> fprintf ppf "single %F" f
+ | Cdouble f -> fprintf ppf "double %F" f
| Csymbol_address s -> fprintf ppf "addr \"%s\"" s
| Clabel_address l -> fprintf ppf "addr L%i" l
| Cstring s -> fprintf ppf "string \"%s\"" s
diff --git a/asmcomp/printmach.ml b/asmcomp/printmach.ml
index 824665cd9d..a39160d28c 100644
--- a/asmcomp/printmach.ml
+++ b/asmcomp/printmach.ml
@@ -105,7 +105,7 @@ let operation op arg ppf res =
| Ireload -> fprintf ppf "%a (reload)" regs arg
| Iconst_int n
| Iconst_blockheader n -> fprintf ppf "%s" (Nativeint.to_string n)
- | Iconst_float s -> fprintf ppf "%s" s
+ | Iconst_float f -> fprintf ppf "%F" f
| Iconst_symbol s -> fprintf ppf "\"%s\"" s
| Icall_ind -> fprintf ppf "call %a" regs arg
| Icall_imm lbl -> fprintf ppf "call \"%s\" %a" lbl regs arg
@@ -119,12 +119,13 @@ let operation op arg ppf res =
| Iload(chunk, addr) ->
fprintf ppf "%s[%a]"
(Printcmm.chunk chunk) (Arch.print_addressing reg addr) arg
- | Istore(chunk, addr) ->
- fprintf ppf "%s[%a] := %a"
+ | Istore(chunk, addr, is_assign) ->
+ fprintf ppf "%s[%a] := %a %s"
(Printcmm.chunk chunk)
(Arch.print_addressing reg addr)
(Array.sub arg 1 (Array.length arg - 1))
reg arg.(0)
+ (if is_assign then "(assign)" else "(init)")
| Ialloc n -> fprintf ppf "alloc %i" n
| Iintop(op) -> fprintf ppf "%a%s%a" reg arg.(0) (intop op) reg arg.(1)
| Iintop_imm(op, n) -> fprintf ppf "%a%s%i" reg arg.(0) (intop op) n
diff --git a/asmcomp/proc.mli b/asmcomp/proc.mli
index 6cc6aedc90..cabac4db7c 100644
--- a/asmcomp/proc.mli
+++ b/asmcomp/proc.mli
@@ -40,6 +40,12 @@ val max_register_pressure: Mach.operation -> int array
val destroyed_at_oper: Mach.instruction_desc -> Reg.t array
val destroyed_at_raise: Reg.t array
+(* Volatile registers: those that change value when read *)
+val regs_are_volatile: Reg.t array -> bool
+
+(* Pure operations *)
+val op_is_pure: Mach.operation -> bool
+
(* Info for laying out the stack frame *)
val num_stack_slots: int array
val contains_calls: bool ref
diff --git a/asmcomp/reg.ml b/asmcomp/reg.ml
index a0fc7dfffa..ef6db5cb6e 100644
--- a/asmcomp/reg.ml
+++ b/asmcomp/reg.ml
@@ -178,6 +178,16 @@ let inter_set_array s v =
else inter_all(i+1)
in inter_all 0
+let disjoint_set_array s v =
+ match Array.length v with
+ 0 -> true
+ | 1 -> not (Set.mem v.(0) s)
+ | n -> let rec disjoint_all i =
+ if i >= n then true
+ else if Set.mem v.(i) s then false
+ else disjoint_all (i+1)
+ in disjoint_all 0
+
let set_of_array v =
match Array.length v with
0 -> Set.empty
diff --git a/asmcomp/reg.mli b/asmcomp/reg.mli
index 34e7498018..e3cb2d9520 100644
--- a/asmcomp/reg.mli
+++ b/asmcomp/reg.mli
@@ -58,6 +58,7 @@ module Map: Map.S with type key = t
val add_set_array: Set.t -> t array -> Set.t
val diff_set_array: Set.t -> t array -> Set.t
val inter_set_array: Set.t -> t array -> Set.t
+val disjoint_set_array: Set.t -> t array -> bool
val set_of_array: t array -> Set.t
val reset: unit -> unit
diff --git a/asmcomp/schedgen.ml b/asmcomp/schedgen.ml
index e04eacd375..f7af443675 100644
--- a/asmcomp/schedgen.ml
+++ b/asmcomp/schedgen.ml
@@ -138,6 +138,8 @@ let some_load = (Iload(Cmm.Word, Arch.identity_addressing))
class virtual scheduler_generic = object (self)
+val mutable trywith_nesting = 0
+
(* Determine whether an operation ends a basic block or not.
Can be overridden for some processors to signal specific instructions
that terminate a basic block. *)
@@ -154,9 +156,16 @@ method oper_in_basic_block = function
(* Determine whether an instruction ends a basic block or not *)
-method private instr_in_basic_block instr =
+(* PR#2719: it is generally incorrect to schedule checkbound instructions
+ within a try ... with Invalid_argument _ -> ...
+ Hence, a checkbound instruction within a try...with block ends the
+ current basic block. *)
+
+method private instr_in_basic_block instr try_nesting =
match instr.desc with
- Lop op -> self#oper_in_basic_block op
+ Lop op ->
+ self#oper_in_basic_block op &&
+ not (try_nesting > 0 && self#is_checkbound op)
| Lreloadretaddr -> true
| _ -> false
@@ -165,7 +174,7 @@ method private instr_in_basic_block instr =
load or store instructions (e.g. on the I386). *)
method is_store = function
- Istore(_, _) -> true
+ Istore(_, _, _) -> true
| _ -> false
method is_load = function
@@ -345,19 +354,21 @@ method private reschedule ready_queue date cont =
method schedule_fundecl f =
- let rec schedule i =
+ let rec schedule i try_nesting =
match i.desc with
- Lend -> i
+ | Lend -> i
+ | Lpushtrap -> { i with next = schedule i.next (try_nesting + 1) }
+ | Lpoptrap -> { i with next = schedule i.next (try_nesting - 1) }
| _ ->
- if self#instr_in_basic_block i then begin
+ if self#instr_in_basic_block i try_nesting then begin
clear_code_dag();
- schedule_block [] i
+ schedule_block [] i try_nesting
end else
- { i with next = schedule i.next }
+ { i with next = schedule i.next try_nesting }
- and schedule_block ready_queue i =
- if self#instr_in_basic_block i then
- schedule_block (self#add_instruction ready_queue i) i.next
+ and schedule_block ready_queue i try_nesting =
+ if self#instr_in_basic_block i try_nesting then
+ schedule_block (self#add_instruction ready_queue i) i.next try_nesting
else begin
let critical_outputs =
match i.desc with
@@ -366,11 +377,11 @@ method schedule_fundecl f =
| Lreturn -> [||]
| _ -> i.arg in
List.iter (fun x -> ignore (longest_path critical_outputs x)) ready_queue;
- self#reschedule ready_queue 0 (schedule i)
+ self#reschedule ready_queue 0 (schedule i try_nesting)
end in
if f.fun_fast then begin
- let new_body = schedule f.fun_body in
+ let new_body = schedule f.fun_body 0 in
clear_code_dag();
{ fun_name = f.fun_name;
fun_body = new_body;
@@ -380,3 +391,5 @@ method schedule_fundecl f =
f
end
+
+let reset () = clear_code_dag ()
diff --git a/asmcomp/schedgen.mli b/asmcomp/schedgen.mli
index 6019d96f42..911330f8ac 100644
--- a/asmcomp/schedgen.mli
+++ b/asmcomp/schedgen.mli
@@ -42,3 +42,5 @@ class virtual scheduler_generic : object
(* Entry point *)
method schedule_fundecl : Linearize.fundecl -> Linearize.fundecl
end
+
+val reset : unit -> unit
diff --git a/asmcomp/selectgen.ml b/asmcomp/selectgen.ml
index a8f073e53a..50a38a244e 100644
--- a/asmcomp/selectgen.ml
+++ b/asmcomp/selectgen.ml
@@ -209,8 +209,8 @@ method virtual select_addressing :
(* Default instruction selection for stores (of words) *)
-method select_store addr arg =
- (Istore(Word, addr), arg)
+method select_store is_assign addr arg =
+ (Istore(Word, addr, is_assign), arg)
(* call marking methods, documented in selectgen.mli *)
@@ -256,10 +256,10 @@ method select_operation op args =
| (Cstore chunk, [arg1; arg2]) ->
let (addr, eloc) = self#select_addressing chunk arg1 in
if chunk = Word then begin
- let (op, newarg2) = self#select_store addr arg2 in
+ let (op, newarg2) = self#select_store true addr arg2 in
(op, [newarg2; eloc])
end else begin
- (Istore(chunk, addr), [arg2; eloc])
+ (Istore(chunk, addr, true), [arg2; eloc])
(* Inversion addr/datum in Istore *)
end
| (Calloc, _) -> (Ialloc 0, args)
@@ -677,16 +677,16 @@ method emit_stores env data regs_addr =
ref (Arch.offset_addressing Arch.identity_addressing (-Arch.size_int)) in
List.iter
(fun e ->
- let (op, arg) = self#select_store !a e in
+ let (op, arg) = self#select_store false !a e in
match self#emit_expr env arg with
None -> assert false
| Some regs ->
match op with
- Istore(_, _) ->
+ Istore(_, _, _) ->
for i = 0 to Array.length regs - 1 do
let r = regs.(i) in
let kind = if r.typ = Float then Double_u else Word in
- self#insert (Iop(Istore(kind, !a)))
+ self#insert (Iop(Istore(kind, !a, false)))
(Array.append [|r|] regs_addr) [||];
a := Arch.offset_addressing !a (size_component r.typ)
done
@@ -857,3 +857,7 @@ let is_tail_call nargs =
let _ =
Simplif.is_tail_native_heuristic := is_tail_call
+
+let reset () =
+ catch_regs := [];
+ current_function_name := ""
diff --git a/asmcomp/selectgen.mli b/asmcomp/selectgen.mli
index 7012c900cc..0de9038215 100644
--- a/asmcomp/selectgen.mli
+++ b/asmcomp/selectgen.mli
@@ -35,7 +35,8 @@ class virtual selector_generic : object
method select_condition : Cmm.expression -> Mach.test * Cmm.expression
(* Can be overridden to deal with special test instructions *)
method select_store :
- Arch.addressing_mode -> Cmm.expression -> Mach.operation * Cmm.expression
+ bool -> Arch.addressing_mode -> Cmm.expression ->
+ Mach.operation * Cmm.expression
(* Can be overridden to deal with special store constant instructions *)
method regs_for : Cmm.machtype -> Reg.t array
(* Return an array of fresh registers of the given type.
@@ -100,3 +101,5 @@ class virtual selector_generic : object
(Ident.t, Reg.t array) Tbl.t -> Cmm.expression -> Reg.t array option
method emit_tail : (Ident.t, Reg.t array) Tbl.t -> Cmm.expression -> unit
end
+
+val reset : unit -> unit
diff --git a/asmcomp/sparc/CSE.ml b/asmcomp/sparc/CSE.ml
new file mode 100644
index 0000000000..c38bab8fe1
--- /dev/null
+++ b/asmcomp/sparc/CSE.ml
@@ -0,0 +1,31 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* CSE for Sparc *)
+
+open Mach
+open CSEgen
+
+class cse = object (self)
+
+inherit cse_generic (* as super *)
+
+method! is_cheap_operation op =
+ match op with
+ | Iconst_int n | Iconst_blockheader n -> n <= 4095n && n >= -4096n
+ | _ -> false
+
+end
+
+let fundecl f =
+ (new cse)#fundecl f
+
diff --git a/asmcomp/sparc/emit.mlp b/asmcomp/sparc/emit.mlp
index 12d60ed327..877a3d52a0 100644
--- a/asmcomp/sparc/emit.mlp
+++ b/asmcomp/sparc/emit.mlp
@@ -190,7 +190,7 @@ let emit_frame fd =
(* Record floating-point constants *)
-let float_constants = ref ([] : (int * string) list)
+let float_constants = ref ([] : (int * int64) list)
let emit_float_constant (lbl, cst) =
rodata ();
@@ -309,11 +309,11 @@ let rec emit_instr i dslot =
` sethi %hi({emit_nativeint n}), %g1\n`;
` or %g1, %lo({emit_nativeint n}), {emit_reg i.res.(0)}\n`
end
- | Lop(Iconst_float s) ->
+ | Lop(Iconst_float f) ->
(* On UltraSPARC, the fzero instruction could be used to set a
floating point register pair to zero. *)
let lbl = new_label() in
- float_constants := (lbl, s) :: !float_constants;
+ float_constants := (lbl, Int64.bits_of_float f) :: !float_constants;
` sethi %hi({emit_label lbl}), %g1\n`;
` ldd [%g1 + %lo({emit_label lbl})], {emit_reg i.res.(0)}\n`
| Lop(Iconst_symbol s) ->
@@ -375,7 +375,7 @@ let rec emit_instr i dslot =
| _ -> "ld" in
emit_load loadinstr addr i.arg dest
end
- | Lop(Istore(chunk, addr)) ->
+ | Lop(Istore(chunk, addr, _)) ->
let src = i.arg.(0) in
begin match chunk with
Double_u ->
@@ -612,7 +612,7 @@ let is_one_instr i =
| Iconst_int n | Iconst_blockheader n -> is_native_immediate n
| Istackoffset _ -> true
| Iload(_, Iindexed n) -> i.res.(0).typ <> Float && is_immediate n
- | Istore(_, Iindexed n) -> i.arg.(0).typ <> Float && is_immediate n
+ | Istore(_, Iindexed n, _) -> i.arg.(0).typ <> Float && is_immediate n
| Iintop(op) -> is_one_instr_op op
| Iintop_imm(op, _) -> is_one_instr_op op
| Iaddf | Isubf | Imulf | Idivf -> true
@@ -706,9 +706,9 @@ let emit_item = function
| Cint n ->
` .word {emit_nativeint n}\n`
| Csingle f ->
- emit_float32_directive ".word" f
+ emit_float32_directive ".word" (Int32.bits_of_float f)
| Cdouble f ->
- emit_float64_split_directive ".word" f
+ emit_float64_split_directive ".word" (Int64.bits_of_float f)
| Csymbol_address s ->
` .word {emit_symbol s}\n`
| Clabel_address lbl ->
diff --git a/asmcomp/sparc/proc.ml b/asmcomp/sparc/proc.ml
index ed107a82a7..ff353d6283 100644
--- a/asmcomp/sparc/proc.ml
+++ b/asmcomp/sparc/proc.ml
@@ -171,6 +171,10 @@ let loc_external_results res =
let loc_exn_bucket = phys_reg 0 (* $o0 *)
+(* Volatile registers: none *)
+
+let regs_are_volatile rs = false
+
(* Registers destroyed by operations *)
let destroyed_at_c_call = (* %l0-%l4, %i0-%i5 preserved *)
@@ -196,6 +200,15 @@ let max_register_pressure = function
Iextcall(_, _) -> [| 11; 0 |]
| _ -> [| 19; 15 |]
+(* Pure operations (without any side effect besides updating their result
+ registers). *)
+
+let op_is_pure = function
+ | Icall_ind | Icall_imm _ | Itailcall_ind | Itailcall_imm _
+ | Iextcall _ | Istackoffset _ | Istore _ | Ialloc _
+ | Iintop(Icheckbound) | Iintop_imm(Icheckbound, _) -> false
+ | _ -> true
+
(* Layout of the stack *)
let num_stack_slots = [| 0; 0 |]
diff --git a/asmcomp/spill.ml b/asmcomp/spill.ml
index ca17fe5bf6..36d1e6812d 100644
--- a/asmcomp/spill.ml
+++ b/asmcomp/spill.ml
@@ -233,7 +233,12 @@ let rec reload i before =
(i, Reg.Set.empty)
| Itrywith(body, handler) ->
let (new_body, after_body) = reload body before in
- let (new_handler, after_handler) = reload handler handler.live in
+ (* All registers live at the beginning of the handler are destroyed,
+ except the exception bucket *)
+ let before_handler =
+ Reg.Set.remove Proc.loc_exn_bucket
+ (Reg.add_set_array handler.live handler.arg) in
+ let (new_handler, after_handler) = reload handler before_handler in
let (new_next, finally) =
reload i.next (Reg.Set.union after_body after_handler) in
(instr_cons (Itrywith(new_body, new_handler)) i.arg i.res new_next,
@@ -384,10 +389,14 @@ let rec spill i finally =
(* Entry point *)
-let fundecl f =
+let reset () =
spill_env := Reg.Map.empty;
use_date := Reg.Map.empty;
- current_date := 0;
+ current_date := 0
+
+let fundecl f =
+ reset ();
+
let (body1, _) = reload f.fun_body Reg.Set.empty in
let (body2, tospill_at_entry) = spill body1 Reg.Set.empty in
let new_body =
diff --git a/asmcomp/spill.mli b/asmcomp/spill.mli
index 66954aef5b..598a175522 100644
--- a/asmcomp/spill.mli
+++ b/asmcomp/spill.mli
@@ -14,3 +14,4 @@
before register allocation. *)
val fundecl: Mach.fundecl -> Mach.fundecl
+val reset : unit -> unit
diff --git a/asmcomp/split.ml b/asmcomp/split.ml
index 9e076e6481..919c980dce 100644
--- a/asmcomp/split.ml
+++ b/asmcomp/split.ml
@@ -195,8 +195,13 @@ let set_repres i =
(* Entry point *)
-let fundecl f =
+let reset () =
equiv_classes := Reg.Map.empty;
+ exit_subst := []
+
+let fundecl f =
+ reset ();
+
let new_args = Array.copy f.fun_args in
let (new_body, sub_body) = rename f.fun_body (Some Reg.Map.empty) in
repres_regs new_args;
diff --git a/asmcomp/split.mli b/asmcomp/split.mli
index f794fec16f..1924a5ad6c 100644
--- a/asmcomp/split.mli
+++ b/asmcomp/split.mli
@@ -13,3 +13,5 @@
(* Renaming of registers at reload points to split live ranges. *)
val fundecl: Mach.fundecl -> Mach.fundecl
+
+val reset : unit -> unit
diff --git a/asmrun/.depend b/asmrun/.depend
index bec9f0c076..5ddaa0d396 100644
--- a/asmrun/.depend
+++ b/asmrun/.depend
@@ -1,756 +1,756 @@
alloc.o: alloc.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/custom.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/stacks.h \
- ../byterun/memory.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/custom.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/stacks.h \
+ ../byterun/memory.h
array.o: array.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h
backtrace.o: backtrace.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/backtrace.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h stack.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/backtrace.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h stack.h
callback.o: callback.c ../byterun/callback.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/mlvalues.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/mlvalues.h
compact.o: compact.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/finalise.h ../byterun/roots.h \
- ../byterun/misc.h ../byterun/config.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/mlvalues.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
- ../byterun/memory.h ../byterun/mlvalues.h ../byterun/roots.h \
- ../byterun/weak.h
+ ../byterun/../config/s.h ../byterun/finalise.h ../byterun/roots.h \
+ ../byterun/misc.h ../byterun/config.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/mlvalues.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
+ ../byterun/memory.h ../byterun/mlvalues.h ../byterun/roots.h \
+ ../byterun/weak.h
compare.o: compare.c ../byterun/custom.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h
custom.o: custom.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/mlvalues.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/mlvalues.h
debugger.o: debugger.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/config.h ../byterun/debugger.h \
- ../byterun/misc.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/config.h ../byterun/debugger.h \
+ ../byterun/misc.h
dynlink.o: dynlink.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/dynlink.h \
- ../byterun/fail.h ../byterun/mlvalues.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/osdeps.h \
- ../byterun/prims.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/dynlink.h \
+ ../byterun/fail.h ../byterun/mlvalues.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/osdeps.h \
+ ../byterun/prims.h
extern.o: extern.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
- ../byterun/gc.h ../byterun/intext.h ../byterun/io.h ../byterun/io.h \
- ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/reverse.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
+ ../byterun/gc.h ../byterun/intext.h ../byterun/io.h ../byterun/io.h \
+ ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/reverse.h
fail.o: fail.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/io.h ../byterun/gc.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/printexc.h \
- ../byterun/signals.h stack.h ../byterun/roots.h ../byterun/memory.h \
- ../byterun/callback.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/io.h ../byterun/gc.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/printexc.h \
+ ../byterun/signals.h stack.h ../byterun/roots.h ../byterun/memory.h \
+ ../byterun/callback.h
finalise.o: finalise.c ../byterun/callback.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/fail.h ../byterun/mlvalues.h \
- ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/signals.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/fail.h ../byterun/mlvalues.h \
+ ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/signals.h
floats.o: floats.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/fail.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/misc.h \
- ../byterun/reverse.h ../byterun/stacks.h ../byterun/memory.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/fail.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/misc.h \
+ ../byterun/reverse.h ../byterun/stacks.h ../byterun/memory.h
freelist.o: freelist.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/freelist.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/gc.h \
- ../byterun/gc_ctrl.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/major_gc.h ../byterun/misc.h ../byterun/mlvalues.h
+ ../byterun/../config/s.h ../byterun/freelist.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/gc.h \
+ ../byterun/gc_ctrl.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/major_gc.h ../byterun/misc.h ../byterun/mlvalues.h
gc_ctrl.o: gc_ctrl.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/compact.h ../byterun/custom.h \
- ../byterun/finalise.h ../byterun/roots.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/freelist.h ../byterun/gc.h \
- ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h stack.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/compact.h ../byterun/custom.h \
+ ../byterun/finalise.h ../byterun/roots.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/freelist.h ../byterun/gc.h \
+ ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h stack.h
globroots.o: globroots.c ../byterun/memory.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/misc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/roots.h ../byterun/memory.h \
- ../byterun/globroots.h ../byterun/roots.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/misc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h ../byterun/roots.h ../byterun/memory.h \
+ ../byterun/globroots.h ../byterun/roots.h
hash.o: hash.c ../byterun/mlvalues.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
- ../byterun/custom.h ../byterun/mlvalues.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/hash.h ../byterun/int64_native.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
+ ../byterun/custom.h ../byterun/mlvalues.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/hash.h ../byterun/int64_native.h
intern.o: intern.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/callback.h ../byterun/custom.h \
- ../byterun/fail.h ../byterun/gc.h ../byterun/intext.h ../byterun/io.h \
- ../byterun/io.h ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/mlvalues.h ../byterun/misc.h ../byterun/reverse.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/callback.h ../byterun/custom.h \
+ ../byterun/fail.h ../byterun/gc.h ../byterun/intext.h ../byterun/io.h \
+ ../byterun/io.h ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/mlvalues.h ../byterun/misc.h ../byterun/reverse.h
ints.o: ints.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/custom.h ../byterun/fail.h ../byterun/intext.h \
- ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/int64_native.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/custom.h ../byterun/fail.h ../byterun/intext.h \
+ ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/int64_native.h
io.o: io.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/custom.h \
- ../byterun/fail.h ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/signals.h \
- ../byterun/sys.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/custom.h \
+ ../byterun/fail.h ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/signals.h \
+ ../byterun/sys.h
lexing.o: lexing.c ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/mlvalues.h ../byterun/stacks.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/mlvalues.h ../byterun/stacks.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h
main.o: main.c ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/misc.h ../byterun/sys.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/misc.h ../byterun/sys.h
major_gc.o: major_gc.c ../byterun/compact.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
- ../byterun/custom.h ../byterun/mlvalues.h ../byterun/config.h \
- ../byterun/fail.h ../byterun/finalise.h ../byterun/roots.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
- ../byterun/weak.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
+ ../byterun/custom.h ../byterun/mlvalues.h ../byterun/config.h \
+ ../byterun/fail.h ../byterun/finalise.h ../byterun/roots.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
+ ../byterun/weak.h
md5.o: md5.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/md5.h ../byterun/io.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/io.h \
- ../byterun/reverse.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/md5.h ../byterun/io.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/io.h \
+ ../byterun/reverse.h
memory.o: memory.c ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/freelist.h ../byterun/gc.h \
- ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/minor_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/signals.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/freelist.h ../byterun/gc.h \
+ ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/minor_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h ../byterun/signals.h
meta.o: meta.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/fail.h ../byterun/fix_code.h \
- ../byterun/interp.h ../byterun/intext.h ../byterun/io.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
- ../byterun/prims.h ../byterun/stacks.h ../byterun/memory.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/config.h ../byterun/fail.h ../byterun/fix_code.h \
+ ../byterun/interp.h ../byterun/intext.h ../byterun/io.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
+ ../byterun/prims.h ../byterun/stacks.h ../byterun/memory.h
minor_gc.o: minor_gc.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/finalise.h \
- ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
- ../byterun/memory.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/roots.h ../byterun/signals.h \
- ../byterun/weak.h
+ ../byterun/../config/s.h ../byterun/fail.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/finalise.h \
+ ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
+ ../byterun/memory.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h ../byterun/roots.h ../byterun/signals.h \
+ ../byterun/weak.h
misc.o: misc.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/mlvalues.h \
- ../byterun/misc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h
+ ../byterun/../config/s.h ../byterun/misc.h ../byterun/config.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/mlvalues.h \
+ ../byterun/misc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h
natdynlink.o: natdynlink.c ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h stack.h ../byterun/callback.h ../byterun/alloc.h \
- ../byterun/intext.h ../byterun/io.h ../byterun/osdeps.h \
- ../byterun/fail.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h stack.h ../byterun/callback.h ../byterun/alloc.h \
+ ../byterun/intext.h ../byterun/io.h ../byterun/osdeps.h \
+ ../byterun/fail.h
obj.o: obj.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/gc.h ../byterun/interp.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
- ../byterun/prims.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/gc.h ../byterun/interp.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
+ ../byterun/prims.h
parsing.o: parsing.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/mlvalues.h ../byterun/config.h \
- ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/alloc.h
+ ../byterun/../config/s.h ../byterun/mlvalues.h ../byterun/config.h \
+ ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/alloc.h
printexc.o: printexc.c ../byterun/backtrace.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/callback.h ../byterun/debugger.h \
- ../byterun/fail.h ../byterun/misc.h ../byterun/mlvalues.h \
- ../byterun/printexc.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/callback.h ../byterun/debugger.h \
+ ../byterun/fail.h ../byterun/misc.h ../byterun/mlvalues.h \
+ ../byterun/printexc.h
roots.o: roots.c ../byterun/finalise.h ../byterun/roots.h \
- ../byterun/misc.h ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/globroots.h ../byterun/memory.h \
- ../byterun/major_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h stack.h ../byterun/roots.h
+ ../byterun/misc.h ../byterun/config.h ../byterun/../config/m.h \
+ ../byterun/../config/s.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/globroots.h ../byterun/memory.h \
+ ../byterun/major_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h stack.h ../byterun/roots.h
signals.o: signals.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/callback.h ../byterun/config.h \
- ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
- ../byterun/memory.h ../byterun/signals.h ../byterun/signals_machdep.h \
- ../byterun/sys.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/callback.h ../byterun/config.h \
+ ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
+ ../byterun/memory.h ../byterun/signals.h ../byterun/signals_machdep.h \
+ ../byterun/sys.h
signals_asm.o: signals_asm.c ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/osdeps.h ../byterun/signals.h ../byterun/signals_machdep.h \
- signals_osdep.h stack.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/osdeps.h ../byterun/signals.h ../byterun/signals_machdep.h \
+ signals_osdep.h stack.h
startup.o: startup.c ../byterun/callback.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/backtrace.h ../byterun/custom.h \
- ../byterun/debugger.h ../byterun/fail.h ../byterun/freelist.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/intext.h ../byterun/io.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/osdeps.h ../byterun/printexc.h stack.h \
- ../byterun/sys.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/backtrace.h ../byterun/custom.h \
+ ../byterun/debugger.h ../byterun/fail.h ../byterun/freelist.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/intext.h \
+ ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/osdeps.h \
+ ../byterun/printexc.h stack.h ../byterun/sys.h
str.o: str.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/mlvalues.h ../byterun/misc.h \
- ../byterun/int64_native.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/mlvalues.h ../byterun/misc.h \
+ ../byterun/int64_native.h
sys.o: sys.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/debugger.h \
- ../byterun/fail.h ../byterun/instruct.h ../byterun/mlvalues.h \
- ../byterun/osdeps.h ../byterun/signals.h ../byterun/stacks.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/sys.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/debugger.h \
+ ../byterun/fail.h ../byterun/instruct.h ../byterun/mlvalues.h \
+ ../byterun/osdeps.h ../byterun/signals.h ../byterun/stacks.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/sys.h
terminfo.o: terminfo.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/fail.h \
- ../byterun/io.h ../byterun/mlvalues.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/fail.h \
+ ../byterun/io.h ../byterun/mlvalues.h
unix.o: unix.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/memory.h ../byterun/config.h \
- ../byterun/gc.h ../byterun/mlvalues.h ../byterun/misc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/osdeps.h
+ ../byterun/../config/s.h ../byterun/memory.h ../byterun/config.h \
+ ../byterun/gc.h ../byterun/mlvalues.h ../byterun/misc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/osdeps.h
weak.o: weak.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h
alloc.d.o: alloc.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/custom.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/stacks.h \
- ../byterun/memory.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/custom.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/stacks.h \
+ ../byterun/memory.h
array.d.o: array.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h
backtrace.d.o: backtrace.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/backtrace.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h stack.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/backtrace.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h stack.h
callback.d.o: callback.c ../byterun/callback.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/mlvalues.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/mlvalues.h
compact.d.o: compact.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/finalise.h ../byterun/roots.h \
- ../byterun/misc.h ../byterun/config.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/mlvalues.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
- ../byterun/memory.h ../byterun/mlvalues.h ../byterun/roots.h \
- ../byterun/weak.h
+ ../byterun/../config/s.h ../byterun/finalise.h ../byterun/roots.h \
+ ../byterun/misc.h ../byterun/config.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/mlvalues.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
+ ../byterun/memory.h ../byterun/mlvalues.h ../byterun/roots.h \
+ ../byterun/weak.h
compare.d.o: compare.c ../byterun/custom.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h
custom.d.o: custom.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/mlvalues.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/mlvalues.h
debugger.d.o: debugger.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/config.h ../byterun/debugger.h \
- ../byterun/misc.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/config.h ../byterun/debugger.h \
+ ../byterun/misc.h
dynlink.d.o: dynlink.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/dynlink.h \
- ../byterun/fail.h ../byterun/mlvalues.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/osdeps.h \
- ../byterun/prims.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/dynlink.h \
+ ../byterun/fail.h ../byterun/mlvalues.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/osdeps.h \
+ ../byterun/prims.h
extern.d.o: extern.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
- ../byterun/gc.h ../byterun/intext.h ../byterun/io.h ../byterun/io.h \
- ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/reverse.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
+ ../byterun/gc.h ../byterun/intext.h ../byterun/io.h ../byterun/io.h \
+ ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/reverse.h
fail.d.o: fail.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/io.h ../byterun/gc.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/printexc.h \
- ../byterun/signals.h stack.h ../byterun/roots.h ../byterun/memory.h \
- ../byterun/callback.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/io.h ../byterun/gc.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/printexc.h \
+ ../byterun/signals.h stack.h ../byterun/roots.h ../byterun/memory.h \
+ ../byterun/callback.h
finalise.d.o: finalise.c ../byterun/callback.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/fail.h ../byterun/mlvalues.h \
- ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/signals.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/fail.h ../byterun/mlvalues.h \
+ ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/signals.h
floats.d.o: floats.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/fail.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/misc.h \
- ../byterun/reverse.h ../byterun/stacks.h ../byterun/memory.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/fail.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/misc.h \
+ ../byterun/reverse.h ../byterun/stacks.h ../byterun/memory.h
freelist.d.o: freelist.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/freelist.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/gc.h \
- ../byterun/gc_ctrl.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/major_gc.h ../byterun/misc.h ../byterun/mlvalues.h
+ ../byterun/../config/s.h ../byterun/freelist.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/gc.h \
+ ../byterun/gc_ctrl.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/major_gc.h ../byterun/misc.h ../byterun/mlvalues.h
gc_ctrl.d.o: gc_ctrl.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/compact.h ../byterun/custom.h \
- ../byterun/finalise.h ../byterun/roots.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/freelist.h ../byterun/gc.h \
- ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h stack.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/compact.h ../byterun/custom.h \
+ ../byterun/finalise.h ../byterun/roots.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/freelist.h ../byterun/gc.h \
+ ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h stack.h
globroots.d.o: globroots.c ../byterun/memory.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/misc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/roots.h ../byterun/memory.h \
- ../byterun/globroots.h ../byterun/roots.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/misc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h ../byterun/roots.h ../byterun/memory.h \
+ ../byterun/globroots.h ../byterun/roots.h
hash.d.o: hash.c ../byterun/mlvalues.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
- ../byterun/custom.h ../byterun/mlvalues.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/hash.h ../byterun/int64_native.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
+ ../byterun/custom.h ../byterun/mlvalues.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/hash.h ../byterun/int64_native.h
intern.d.o: intern.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/callback.h ../byterun/custom.h \
- ../byterun/fail.h ../byterun/gc.h ../byterun/intext.h ../byterun/io.h \
- ../byterun/io.h ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/mlvalues.h ../byterun/misc.h ../byterun/reverse.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/callback.h ../byterun/custom.h \
+ ../byterun/fail.h ../byterun/gc.h ../byterun/intext.h ../byterun/io.h \
+ ../byterun/io.h ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/mlvalues.h ../byterun/misc.h ../byterun/reverse.h
ints.d.o: ints.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/custom.h ../byterun/fail.h ../byterun/intext.h \
- ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/int64_native.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/custom.h ../byterun/fail.h ../byterun/intext.h \
+ ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/int64_native.h
io.d.o: io.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/custom.h \
- ../byterun/fail.h ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/signals.h \
- ../byterun/sys.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/custom.h \
+ ../byterun/fail.h ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/signals.h \
+ ../byterun/sys.h
lexing.d.o: lexing.c ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/mlvalues.h ../byterun/stacks.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/mlvalues.h ../byterun/stacks.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h
main.d.o: main.c ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/misc.h ../byterun/sys.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/misc.h ../byterun/sys.h
major_gc.d.o: major_gc.c ../byterun/compact.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
- ../byterun/custom.h ../byterun/mlvalues.h ../byterun/config.h \
- ../byterun/fail.h ../byterun/finalise.h ../byterun/roots.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
- ../byterun/weak.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
+ ../byterun/custom.h ../byterun/mlvalues.h ../byterun/config.h \
+ ../byterun/fail.h ../byterun/finalise.h ../byterun/roots.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
+ ../byterun/weak.h
md5.d.o: md5.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/md5.h ../byterun/io.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/io.h \
- ../byterun/reverse.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/md5.h ../byterun/io.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/io.h \
+ ../byterun/reverse.h
memory.d.o: memory.c ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/freelist.h ../byterun/gc.h \
- ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/minor_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/signals.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/freelist.h ../byterun/gc.h \
+ ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/minor_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h ../byterun/signals.h
meta.d.o: meta.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/fail.h ../byterun/fix_code.h \
- ../byterun/interp.h ../byterun/intext.h ../byterun/io.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
- ../byterun/prims.h ../byterun/stacks.h ../byterun/memory.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/config.h ../byterun/fail.h ../byterun/fix_code.h \
+ ../byterun/interp.h ../byterun/intext.h ../byterun/io.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
+ ../byterun/prims.h ../byterun/stacks.h ../byterun/memory.h
minor_gc.d.o: minor_gc.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/finalise.h \
- ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
- ../byterun/memory.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/roots.h ../byterun/signals.h \
- ../byterun/weak.h
+ ../byterun/../config/s.h ../byterun/fail.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/finalise.h \
+ ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
+ ../byterun/memory.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h ../byterun/roots.h ../byterun/signals.h \
+ ../byterun/weak.h
misc.d.o: misc.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/mlvalues.h \
- ../byterun/misc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h
+ ../byterun/../config/s.h ../byterun/misc.h ../byterun/config.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/mlvalues.h \
+ ../byterun/misc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h
natdynlink.d.o: natdynlink.c ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h stack.h ../byterun/callback.h ../byterun/alloc.h \
- ../byterun/intext.h ../byterun/io.h ../byterun/osdeps.h \
- ../byterun/fail.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h stack.h ../byterun/callback.h ../byterun/alloc.h \
+ ../byterun/intext.h ../byterun/io.h ../byterun/osdeps.h \
+ ../byterun/fail.h
obj.d.o: obj.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/gc.h ../byterun/interp.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
- ../byterun/prims.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/gc.h ../byterun/interp.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
+ ../byterun/prims.h
parsing.d.o: parsing.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/mlvalues.h ../byterun/config.h \
- ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/alloc.h
+ ../byterun/../config/s.h ../byterun/mlvalues.h ../byterun/config.h \
+ ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/alloc.h
printexc.d.o: printexc.c ../byterun/backtrace.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/callback.h ../byterun/debugger.h \
- ../byterun/fail.h ../byterun/misc.h ../byterun/mlvalues.h \
- ../byterun/printexc.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/callback.h ../byterun/debugger.h \
+ ../byterun/fail.h ../byterun/misc.h ../byterun/mlvalues.h \
+ ../byterun/printexc.h
roots.d.o: roots.c ../byterun/finalise.h ../byterun/roots.h \
- ../byterun/misc.h ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/globroots.h ../byterun/memory.h \
- ../byterun/major_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h stack.h ../byterun/roots.h
+ ../byterun/misc.h ../byterun/config.h ../byterun/../config/m.h \
+ ../byterun/../config/s.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/globroots.h ../byterun/memory.h \
+ ../byterun/major_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h stack.h ../byterun/roots.h
signals.d.o: signals.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/callback.h ../byterun/config.h \
- ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
- ../byterun/memory.h ../byterun/signals.h ../byterun/signals_machdep.h \
- ../byterun/sys.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/callback.h ../byterun/config.h \
+ ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
+ ../byterun/memory.h ../byterun/signals.h ../byterun/signals_machdep.h \
+ ../byterun/sys.h
signals_asm.d.o: signals_asm.c ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/osdeps.h ../byterun/signals.h ../byterun/signals_machdep.h \
- signals_osdep.h stack.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/osdeps.h ../byterun/signals.h ../byterun/signals_machdep.h \
+ signals_osdep.h stack.h
startup.d.o: startup.c ../byterun/callback.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/backtrace.h ../byterun/custom.h \
- ../byterun/debugger.h ../byterun/fail.h ../byterun/freelist.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/intext.h ../byterun/io.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/osdeps.h ../byterun/printexc.h stack.h \
- ../byterun/sys.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/backtrace.h ../byterun/custom.h \
+ ../byterun/debugger.h ../byterun/fail.h ../byterun/freelist.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/intext.h \
+ ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/osdeps.h \
+ ../byterun/printexc.h stack.h ../byterun/sys.h
str.d.o: str.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/mlvalues.h ../byterun/misc.h \
- ../byterun/int64_native.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/mlvalues.h ../byterun/misc.h \
+ ../byterun/int64_native.h
sys.d.o: sys.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/debugger.h \
- ../byterun/fail.h ../byterun/instruct.h ../byterun/mlvalues.h \
- ../byterun/osdeps.h ../byterun/signals.h ../byterun/stacks.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/sys.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/debugger.h \
+ ../byterun/fail.h ../byterun/instruct.h ../byterun/mlvalues.h \
+ ../byterun/osdeps.h ../byterun/signals.h ../byterun/stacks.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/sys.h
terminfo.d.o: terminfo.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/fail.h \
- ../byterun/io.h ../byterun/mlvalues.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/fail.h \
+ ../byterun/io.h ../byterun/mlvalues.h
unix.d.o: unix.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/memory.h ../byterun/config.h \
- ../byterun/gc.h ../byterun/mlvalues.h ../byterun/misc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/osdeps.h
+ ../byterun/../config/s.h ../byterun/memory.h ../byterun/config.h \
+ ../byterun/gc.h ../byterun/mlvalues.h ../byterun/misc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/osdeps.h
weak.d.o: weak.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h
alloc.p.o: alloc.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/custom.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/stacks.h \
- ../byterun/memory.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/custom.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/stacks.h \
+ ../byterun/memory.h
array.p.o: array.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h
backtrace.p.o: backtrace.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/backtrace.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h stack.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/backtrace.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h stack.h
callback.p.o: callback.c ../byterun/callback.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/mlvalues.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/mlvalues.h
compact.p.o: compact.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/finalise.h ../byterun/roots.h \
- ../byterun/misc.h ../byterun/config.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/mlvalues.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
- ../byterun/memory.h ../byterun/mlvalues.h ../byterun/roots.h \
- ../byterun/weak.h
+ ../byterun/../config/s.h ../byterun/finalise.h ../byterun/roots.h \
+ ../byterun/misc.h ../byterun/config.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/mlvalues.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
+ ../byterun/memory.h ../byterun/mlvalues.h ../byterun/roots.h \
+ ../byterun/weak.h
compare.p.o: compare.c ../byterun/custom.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h
custom.p.o: custom.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/mlvalues.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/mlvalues.h
debugger.p.o: debugger.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/config.h ../byterun/debugger.h \
- ../byterun/misc.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/config.h ../byterun/debugger.h \
+ ../byterun/misc.h
dynlink.p.o: dynlink.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/dynlink.h \
- ../byterun/fail.h ../byterun/mlvalues.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/osdeps.h \
- ../byterun/prims.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/dynlink.h \
+ ../byterun/fail.h ../byterun/mlvalues.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/osdeps.h \
+ ../byterun/prims.h
extern.p.o: extern.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
- ../byterun/gc.h ../byterun/intext.h ../byterun/io.h ../byterun/io.h \
- ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/reverse.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/custom.h ../byterun/fail.h \
+ ../byterun/gc.h ../byterun/intext.h ../byterun/io.h ../byterun/io.h \
+ ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/reverse.h
fail.p.o: fail.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/io.h ../byterun/gc.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/printexc.h \
- ../byterun/signals.h stack.h ../byterun/roots.h ../byterun/memory.h \
- ../byterun/callback.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/io.h ../byterun/gc.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/printexc.h \
+ ../byterun/signals.h stack.h ../byterun/roots.h ../byterun/memory.h \
+ ../byterun/callback.h
finalise.p.o: finalise.c ../byterun/callback.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/fail.h ../byterun/mlvalues.h \
- ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/signals.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/fail.h ../byterun/mlvalues.h \
+ ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/signals.h
floats.p.o: floats.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/fail.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/misc.h \
- ../byterun/reverse.h ../byterun/stacks.h ../byterun/memory.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/fail.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/misc.h \
+ ../byterun/reverse.h ../byterun/stacks.h ../byterun/memory.h
freelist.p.o: freelist.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/freelist.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/gc.h \
- ../byterun/gc_ctrl.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/major_gc.h ../byterun/misc.h ../byterun/mlvalues.h
+ ../byterun/../config/s.h ../byterun/freelist.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/gc.h \
+ ../byterun/gc_ctrl.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/major_gc.h ../byterun/misc.h ../byterun/mlvalues.h
gc_ctrl.p.o: gc_ctrl.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/compact.h ../byterun/custom.h \
- ../byterun/finalise.h ../byterun/roots.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/freelist.h ../byterun/gc.h \
- ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h stack.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/compact.h ../byterun/custom.h \
+ ../byterun/finalise.h ../byterun/roots.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/freelist.h ../byterun/gc.h \
+ ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h stack.h
globroots.p.o: globroots.c ../byterun/memory.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/misc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/roots.h ../byterun/memory.h \
- ../byterun/globroots.h ../byterun/roots.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/misc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h ../byterun/roots.h ../byterun/memory.h \
+ ../byterun/globroots.h ../byterun/roots.h
hash.p.o: hash.c ../byterun/mlvalues.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
- ../byterun/custom.h ../byterun/mlvalues.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/hash.h ../byterun/int64_native.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
+ ../byterun/custom.h ../byterun/mlvalues.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/hash.h ../byterun/int64_native.h
intern.p.o: intern.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/callback.h ../byterun/custom.h \
- ../byterun/fail.h ../byterun/gc.h ../byterun/intext.h ../byterun/io.h \
- ../byterun/io.h ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/mlvalues.h ../byterun/misc.h ../byterun/reverse.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/callback.h ../byterun/custom.h \
+ ../byterun/fail.h ../byterun/gc.h ../byterun/intext.h ../byterun/io.h \
+ ../byterun/io.h ../byterun/md5.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/mlvalues.h ../byterun/misc.h ../byterun/reverse.h
ints.p.o: ints.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/custom.h ../byterun/fail.h ../byterun/intext.h \
- ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/int64_native.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/custom.h ../byterun/fail.h ../byterun/intext.h \
+ ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/int64_native.h
io.p.o: io.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/custom.h \
- ../byterun/fail.h ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/signals.h \
- ../byterun/sys.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/custom.h \
+ ../byterun/fail.h ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/signals.h \
+ ../byterun/sys.h
lexing.p.o: lexing.c ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/mlvalues.h ../byterun/stacks.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/mlvalues.h ../byterun/stacks.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h
main.p.o: main.c ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/misc.h ../byterun/sys.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/misc.h ../byterun/sys.h
major_gc.p.o: major_gc.c ../byterun/compact.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
- ../byterun/custom.h ../byterun/mlvalues.h ../byterun/config.h \
- ../byterun/fail.h ../byterun/finalise.h ../byterun/roots.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
- ../byterun/weak.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/misc.h \
+ ../byterun/custom.h ../byterun/mlvalues.h ../byterun/config.h \
+ ../byterun/fail.h ../byterun/finalise.h ../byterun/roots.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/freelist.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
+ ../byterun/weak.h
md5.p.o: md5.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/md5.h ../byterun/io.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/io.h \
- ../byterun/reverse.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/md5.h ../byterun/io.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h ../byterun/io.h \
+ ../byterun/reverse.h
memory.p.o: memory.c ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/freelist.h ../byterun/gc.h \
- ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/minor_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/signals.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/freelist.h ../byterun/gc.h \
+ ../byterun/gc_ctrl.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/minor_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h ../byterun/signals.h
meta.p.o: meta.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/fail.h ../byterun/fix_code.h \
- ../byterun/interp.h ../byterun/intext.h ../byterun/io.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
- ../byterun/prims.h ../byterun/stacks.h ../byterun/memory.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/config.h ../byterun/fail.h ../byterun/fix_code.h \
+ ../byterun/interp.h ../byterun/intext.h ../byterun/io.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
+ ../byterun/prims.h ../byterun/stacks.h ../byterun/memory.h
minor_gc.p.o: minor_gc.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/finalise.h \
- ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
- ../byterun/memory.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/roots.h ../byterun/signals.h \
- ../byterun/weak.h
+ ../byterun/../config/s.h ../byterun/fail.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/finalise.h \
+ ../byterun/roots.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/major_gc.h \
+ ../byterun/memory.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h ../byterun/roots.h ../byterun/signals.h \
+ ../byterun/weak.h
misc.p.o: misc.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/mlvalues.h \
- ../byterun/misc.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h
+ ../byterun/../config/s.h ../byterun/misc.h ../byterun/config.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/mlvalues.h \
+ ../byterun/misc.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h
natdynlink.p.o: natdynlink.c ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h stack.h ../byterun/callback.h ../byterun/alloc.h \
- ../byterun/intext.h ../byterun/io.h ../byterun/osdeps.h \
- ../byterun/fail.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h stack.h ../byterun/callback.h ../byterun/alloc.h \
+ ../byterun/intext.h ../byterun/io.h ../byterun/osdeps.h \
+ ../byterun/fail.h
obj.p.o: obj.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/gc.h ../byterun/interp.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
- ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
- ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
- ../byterun/prims.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/gc.h ../byterun/interp.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/memory.h \
+ ../byterun/gc.h ../byterun/major_gc.h ../byterun/minor_gc.h \
+ ../byterun/minor_gc.h ../byterun/misc.h ../byterun/mlvalues.h \
+ ../byterun/prims.h
parsing.p.o: parsing.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/mlvalues.h ../byterun/config.h \
- ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/alloc.h
+ ../byterun/../config/s.h ../byterun/mlvalues.h ../byterun/config.h \
+ ../byterun/misc.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/alloc.h
printexc.p.o: printexc.c ../byterun/backtrace.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/callback.h ../byterun/debugger.h \
- ../byterun/fail.h ../byterun/misc.h ../byterun/mlvalues.h \
- ../byterun/printexc.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/callback.h ../byterun/debugger.h \
+ ../byterun/fail.h ../byterun/misc.h ../byterun/mlvalues.h \
+ ../byterun/printexc.h
roots.p.o: roots.c ../byterun/finalise.h ../byterun/roots.h \
- ../byterun/misc.h ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/minor_gc.h ../byterun/globroots.h ../byterun/memory.h \
- ../byterun/major_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h stack.h ../byterun/roots.h
+ ../byterun/misc.h ../byterun/config.h ../byterun/../config/m.h \
+ ../byterun/../config/s.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/mlvalues.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/minor_gc.h ../byterun/globroots.h ../byterun/memory.h \
+ ../byterun/major_gc.h ../byterun/minor_gc.h ../byterun/misc.h \
+ ../byterun/mlvalues.h stack.h ../byterun/roots.h
signals.p.o: signals.c ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/callback.h ../byterun/config.h \
- ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
- ../byterun/memory.h ../byterun/signals.h ../byterun/signals_machdep.h \
- ../byterun/sys.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/callback.h ../byterun/config.h \
+ ../byterun/fail.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/roots.h \
+ ../byterun/memory.h ../byterun/signals.h ../byterun/signals_machdep.h \
+ ../byterun/sys.h
signals_asm.p.o: signals_asm.c ../byterun/fail.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/mlvalues.h ../byterun/memory.h ../byterun/gc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/osdeps.h ../byterun/signals.h ../byterun/signals_machdep.h \
- signals_osdep.h stack.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/mlvalues.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/osdeps.h ../byterun/signals.h ../byterun/signals_machdep.h \
+ signals_osdep.h stack.h
startup.p.o: startup.c ../byterun/callback.h ../byterun/mlvalues.h \
- ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
- ../byterun/misc.h ../byterun/backtrace.h ../byterun/custom.h \
- ../byterun/debugger.h ../byterun/fail.h ../byterun/freelist.h \
- ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/intext.h ../byterun/io.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/misc.h \
- ../byterun/mlvalues.h ../byterun/osdeps.h ../byterun/printexc.h stack.h \
- ../byterun/sys.h
+ ../byterun/config.h ../byterun/../config/m.h ../byterun/../config/s.h \
+ ../byterun/misc.h ../byterun/backtrace.h ../byterun/custom.h \
+ ../byterun/debugger.h ../byterun/fail.h ../byterun/freelist.h \
+ ../byterun/gc.h ../byterun/gc_ctrl.h ../byterun/intext.h \
+ ../byterun/io.h ../byterun/memory.h ../byterun/gc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/mlvalues.h ../byterun/osdeps.h \
+ ../byterun/printexc.h stack.h ../byterun/sys.h
str.p.o: str.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/mlvalues.h ../byterun/misc.h \
- ../byterun/int64_native.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/mlvalues.h ../byterun/misc.h \
+ ../byterun/int64_native.h
sys.p.o: sys.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/debugger.h \
- ../byterun/fail.h ../byterun/instruct.h ../byterun/mlvalues.h \
- ../byterun/osdeps.h ../byterun/signals.h ../byterun/stacks.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/sys.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/debugger.h \
+ ../byterun/fail.h ../byterun/instruct.h ../byterun/mlvalues.h \
+ ../byterun/osdeps.h ../byterun/signals.h ../byterun/stacks.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/freelist.h ../byterun/minor_gc.h ../byterun/sys.h
terminfo.p.o: terminfo.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
- ../byterun/config.h ../byterun/mlvalues.h ../byterun/fail.h \
- ../byterun/io.h ../byterun/mlvalues.h
+ ../byterun/../config/s.h ../byterun/alloc.h ../byterun/misc.h \
+ ../byterun/config.h ../byterun/mlvalues.h ../byterun/fail.h \
+ ../byterun/io.h ../byterun/mlvalues.h
unix.p.o: unix.c ../byterun/config.h ../byterun/../config/m.h \
- ../byterun/../config/s.h ../byterun/memory.h ../byterun/config.h \
- ../byterun/gc.h ../byterun/mlvalues.h ../byterun/misc.h \
- ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
- ../byterun/misc.h ../byterun/osdeps.h
+ ../byterun/../config/s.h ../byterun/memory.h ../byterun/config.h \
+ ../byterun/gc.h ../byterun/mlvalues.h ../byterun/misc.h \
+ ../byterun/major_gc.h ../byterun/freelist.h ../byterun/minor_gc.h \
+ ../byterun/misc.h ../byterun/osdeps.h
weak.p.o: weak.c ../byterun/alloc.h ../byterun/misc.h ../byterun/config.h \
- ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
- ../byterun/fail.h ../byterun/major_gc.h ../byterun/freelist.h \
- ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
- ../byterun/minor_gc.h ../byterun/mlvalues.h
+ ../byterun/../config/m.h ../byterun/../config/s.h ../byterun/mlvalues.h \
+ ../byterun/fail.h ../byterun/major_gc.h ../byterun/freelist.h \
+ ../byterun/memory.h ../byterun/gc.h ../byterun/major_gc.h \
+ ../byterun/minor_gc.h ../byterun/mlvalues.h
diff --git a/asmrun/Makefile b/asmrun/Makefile
index 6c6dd98a8e..63ff80c687 100644
--- a/asmrun/Makefile
+++ b/asmrun/Makefile
@@ -183,7 +183,7 @@ clean::
exit 2; }
.S.p.o:
- $(ASPP) -DSYS_$(SYSTEM) $(ASPPPROFFLAGS) -o $*.p.o $*.S
+ $(ASPP) -DSYS_$(SYSTEM) -DMODEL_$(MODEL) $(ASPPPROFFLAGS) -o $*.p.o $*.S
.c.d.o:
ln -s -f $*.c $*.d.c
diff --git a/asmrun/arm64.S b/asmrun/arm64.S
index 2c16a0eadb..fa871df797 100644
--- a/asmrun/arm64.S
+++ b/asmrun/arm64.S
@@ -478,7 +478,7 @@ caml_callback2_exn:
/* 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 x1, x2 /* x1 = second arg */
mov x2, TMP /* x2 = closure environment */
ADDRGLOBAL(ARG, caml_apply2)
b .Ljump_to_caml
diff --git a/asmrun/backtrace.c b/asmrun/backtrace.c
index 3854967cf4..c72a2373b9 100644
--- a/asmrun/backtrace.c
+++ b/asmrun/backtrace.c
@@ -30,6 +30,17 @@ code_t * caml_backtrace_buffer = NULL;
value caml_backtrace_last_exn = Val_unit;
#define BACKTRACE_BUFFER_SIZE 1024
+/* In order to prevent the GC from walking through the debug information
+ (which have no headers), we transform frame_descr pointers into
+ 31/63 bits ocaml integers by shifting them by 1 to the right. We do
+ not lose information as descr pointers are aligned.
+
+ In particular, we do not need to use [caml_initialize] when setting
+ an array element with such a value.
+*/
+#define Val_Descrptr(descr) Val_long((uintnat)descr>>1)
+#define Descrptr_Val(v) ((frame_descr *) (Long_val(v)<<1))
+
/* Start or stop the backtrace machinery */
CAMLprim value caml_record_backtrace(value vflag)
@@ -112,6 +123,7 @@ void caml_stash_backtrace(value exn, uintnat pc, char * sp, char * trapsp)
caml_backtrace_last_exn = exn;
}
if (caml_backtrace_buffer == NULL) {
+ Assert(caml_backtrace_pos == 0);
caml_backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE * sizeof(code_t));
if (caml_backtrace_buffer == NULL) return;
}
@@ -172,7 +184,7 @@ CAMLprim value caml_get_current_callstack(value max_frames_value) {
}
}
- trace = caml_alloc((mlsize_t) trace_size, Abstract_tag);
+ trace = caml_alloc((mlsize_t) trace_size, 0);
/* then collect the trace */
{
@@ -183,11 +195,7 @@ CAMLprim value caml_get_current_callstack(value max_frames_value) {
for (trace_pos = 0; trace_pos < trace_size; trace_pos++) {
frame_descr * descr = caml_next_frame_descriptor(&pc, &sp);
Assert(descr != NULL);
- /* The assignment below is safe without [caml_initialize], even
- if the trace is large and allocated on the old heap, because
- we assign values that are outside the OCaml heap. */
- Assert(!(Is_block((value) descr) && Is_in_heap((value) descr)));
- Field(trace, trace_pos) = (value) descr;
+ Field(trace, trace_pos) = Val_Descrptr(descr);
}
}
@@ -295,31 +303,27 @@ void caml_print_exception_backtrace(void)
/* Convert the raw backtrace to a data structure usable from OCaml */
-CAMLprim value caml_convert_raw_backtrace(value backtrace) {
- CAMLparam1(backtrace);
- CAMLlocal4(res, arr, p, fname);
- int i;
+CAMLprim value caml_convert_raw_backtrace_slot(value backtrace_slot) {
+ CAMLparam1(backtrace_slot);
+ CAMLlocal2(p, fname);
struct loc_info li;
- arr = caml_alloc(Wosize_val(backtrace), 0);
- for (i = 0; i < Wosize_val(backtrace); i++) {
- extract_location_info((frame_descr *) Field(backtrace, i), &li);
- if (li.loc_valid) {
- fname = caml_copy_string(li.loc_filename);
- p = caml_alloc_small(5, 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);
- } else {
- p = caml_alloc_small(1, 1);
- Field(p, 0) = Val_bool(li.loc_is_raise);
- }
- caml_modify(&Field(arr, i), p);
+ extract_location_info(Descrptr_Val(backtrace_slot), &li);
+
+ if (li.loc_valid) {
+ fname = caml_copy_string(li.loc_filename);
+ p = caml_alloc_small(5, 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);
+ } else {
+ p = caml_alloc_small(1, 1);
+ Field(p, 0) = Val_bool(li.loc_is_raise);
}
- res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */
- CAMLreturn(res);
+
+ CAMLreturn(p);
}
/* Get a copy of the latest backtrace */
@@ -328,10 +332,13 @@ CAMLprim value caml_get_exception_raw_backtrace(value unit)
{
CAMLparam0();
CAMLlocal1(res);
- res = caml_alloc(caml_backtrace_pos, Abstract_tag);
- if(caml_backtrace_buffer != NULL)
- memcpy(&Field(res, 0), caml_backtrace_buffer,
- caml_backtrace_pos * sizeof(code_t));
+
+ res = caml_alloc(caml_backtrace_pos, 0);
+ if(caml_backtrace_buffer != NULL) {
+ intnat i;
+ for(i = 0; i < caml_backtrace_pos; i++)
+ Field(res, i) = Val_Descrptr(caml_backtrace_buffer[i]);
+ }
CAMLreturn(res);
}
@@ -348,8 +355,19 @@ CAMLprim value caml_get_exception_raw_backtrace(value unit)
CAMLprim value caml_get_exception_backtrace(value unit)
{
CAMLparam0();
- CAMLlocal2(raw,res);
- raw = caml_get_exception_raw_backtrace(unit);
- res = caml_convert_raw_backtrace(raw);
+ CAMLlocal4(arr, raw_slot, slot, res);
+
+ arr = caml_alloc(caml_backtrace_pos, 0);
+ if (caml_backtrace_buffer == NULL) {
+ Assert(caml_backtrace_pos == 0);
+ } else {
+ intnat i;
+ for(i = 0; i < caml_backtrace_pos; i++) {
+ raw_slot = Val_Descrptr(caml_backtrace_buffer[i]);
+ slot = caml_convert_raw_backtrace_slot(raw_slot);
+ caml_modify(&Field(arr, i), slot);
+ }
+ }
+ res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */
CAMLreturn(res);
}
diff --git a/asmrun/fail.c b/asmrun/fail.c
index be625e10e5..cb2c1cbd77 100644
--- a/asmrun/fail.c
+++ b/asmrun/fail.c
@@ -104,7 +104,10 @@ void caml_raise_with_args(value tag, int nargs, value args[])
void caml_raise_with_string(value tag, char const *msg)
{
- caml_raise_with_arg(tag, caml_copy_string(msg));
+ CAMLparam1(tag);
+ value v_msg = caml_copy_string(msg);
+ caml_raise_with_arg(tag, v_msg);
+ CAMLnoreturn;
}
void caml_failwith (char const *msg)
diff --git a/asmrun/i386.S b/asmrun/i386.S
index f880db2574..347e967c14 100644
--- a/asmrun/i386.S
+++ b/asmrun/i386.S
@@ -115,13 +115,10 @@
#define PROFILE_C
#endif
-#ifdef SYS_macosx
+/* PR#6038: GCC and Clang seem to require 16-byte alignment nowadays,
+ even if only MacOS X's ABI formally requires it. */
#define ALIGN_STACK(amount) subl $ amount, %esp ; CFI_ADJUST(amount)
#define UNDO_ALIGN_STACK(amount) addl $ amount, %esp ; CFI_ADJUST(-amount)
-#else
-#define ALIGN_STACK(amount)
-#define UNDO_ALIGN_STACK(amount)
-#endif
/* Allocation */
@@ -304,11 +301,7 @@ LBL(106):
LBL(107):
/* Pop the exception handler */
popl G(caml_exception_pointer); CFI_ADJUST(-4)
-#ifdef SYS_macosx
addl $12, %esp ; CFI_ADJUST(-12)
-#else
- addl $4, %esp ; CFI_ADJUST(-4)
-#endif
LBL(109):
/* Pop the callback link, restoring the global variables */
popl G(caml_bottom_of_stack); CFI_ADJUST(-4)
@@ -461,10 +454,8 @@ FUNCTION(caml_ml_array_bound_error)
movl %edx, G(caml_last_return_address)
leal 4(%esp), %edx
movl %edx, G(caml_bottom_of_stack)
- /* For MacOS X: re-align the stack */
-#ifdef SYS_macosx
+ /* Re-align the stack */
andl $-16, %esp
-#endif
/* Branch to [caml_array_bound_error] (never returns) */
call G(caml_array_bound_error)
CFI_ENDPROC
diff --git a/asmrun/natdynlink.c b/asmrun/natdynlink.c
index edb389dbb0..86c4f3e6f3 100644
--- a/asmrun/natdynlink.c
+++ b/asmrun/natdynlink.c
@@ -25,12 +25,11 @@
#include <string.h>
static void *getsym(void *handle, char *module, char *name){
- char *fullname = malloc(strlen(module) + strlen(name) + 5);
+ char *fullname = caml_strconcat(3, "caml", module, name);
void *sym;
- sprintf(fullname, "caml%s%s", module, name);
sym = caml_dlsym (handle, fullname);
/* printf("%s => %lx\n", fullname, (uintnat) sym); */
- free(fullname);
+ caml_stat_free(fullname);
return sym;
}
diff --git a/asmrun/signals_osdep.h b/asmrun/signals_osdep.h
index 573e3a5716..23165ad680 100644
--- a/asmrun/signals_osdep.h
+++ b/asmrun/signals_osdep.h
@@ -267,9 +267,11 @@
sigact.sa_flags = 0
typedef unsigned long context_reg;
+ #define CONTEXT_PC (context->sc_frame.srr0)
#define CONTEXT_EXCEPTION_POINTER (context->sc_frame.fixreg[29])
#define CONTEXT_YOUNG_LIMIT (context->sc_frame.fixreg[30])
#define CONTEXT_YOUNG_PTR (context->sc_frame.fixreg[31])
+ #define CONTEXT_SP (context->sc_frame.fixreg[1])
/****************** SPARC, Solaris */
@@ -288,6 +290,7 @@
#define CONTEXT_PC (context->uc_mcontext.gregs[REG_PC])
/* Local register number N is saved on the stack N words
after the stack pointer */
+ #define CONTEXT_SP (context->uc_mcontext.gregs[REG_SP])
#define SPARC_L_REG(n) ((long *)(context->uc_mcontext.gregs[REG_SP]))[n]
#define CONTEXT_EXCEPTION_POINTER (SPARC_L_REG(5))
#define CONTEXT_YOUNG_LIMIT (SPARC_L_REG(7))
diff --git a/asmrun/stack.h b/asmrun/stack.h
index 9abd6e9ce0..92b3c28a35 100644
--- a/asmrun/stack.h
+++ b/asmrun/stack.h
@@ -25,7 +25,7 @@
#ifdef TARGET_i386
#define Saved_return_address(sp) *((intnat *)((sp) - 4))
-#ifdef SYS_macosx
+#ifndef SYS_win32
#define Callback_link(sp) ((struct caml_context *)((sp) + 16))
#else
#define Callback_link(sp) ((struct caml_context *)((sp) + 8))
diff --git a/boot/ocamlc b/boot/ocamlc
index e2cbf0b76e..30553fc841 100755
--- a/boot/ocamlc
+++ b/boot/ocamlc
Binary files differ
diff --git a/boot/ocamldep b/boot/ocamldep
index eeacb89e5a..409f30f971 100755
--- a/boot/ocamldep
+++ b/boot/ocamldep
Binary files differ
diff --git a/boot/ocamllex b/boot/ocamllex
index 4f0a44e8b8..be5e1a4640 100755
--- a/boot/ocamllex
+++ b/boot/ocamllex
Binary files differ
diff --git a/bytecomp/bytegen.ml b/bytecomp/bytegen.ml
index 47349d6f35..1a3767969c 100644
--- a/bytecomp/bytegen.ml
+++ b/bytecomp/bytegen.ml
@@ -146,7 +146,7 @@ let rec size_of_lambda = function
begin match kind with
| Record_regular | Record_inlined _ -> RHS_block size
| Record_float -> RHS_floatblock size
- | Record_exception _ -> RHS_block (size + 1)
+ | Record_extension _ -> RHS_block (size + 1)
end
| Llet(str, id, arg, body) -> size_of_lambda body
| Lletrec(bindings, body) -> size_of_lambda body
@@ -157,7 +157,7 @@ let rec size_of_lambda = function
| Lprim (Pmakearray Pgenarray, args) -> assert false
| Lprim (Pduprecord ((Record_regular | Record_inlined _), size), args) ->
RHS_block size
- | Lprim (Pduprecord (Record_exception _, size), args) ->
+ | Lprim (Pduprecord (Record_extension _, size), args) ->
RHS_block (size + 1)
| Lprim (Pduprecord (Record_float, size), args) -> RHS_floatblock size
| Levent (lam, _) -> size_of_lambda lam
@@ -237,9 +237,15 @@ let add_event ev =
(**** Compilation of a lambda expression ****)
-(* association staticraise numbers -> (lbl,size of stack *)
+let try_blocks = ref [] (* list of stack size for each nested try block *)
+
+(* association staticraise numbers -> (lbl,size of stack, try_blocks *)
let sz_static_raises = ref []
+
+let push_static_raise i lbl_handler sz =
+ sz_static_raises := (i, (lbl_handler, sz, !try_blocks)) :: !sz_static_raises
+
let find_raise_label i =
try
List.assoc i !sz_static_raises
@@ -251,8 +257,8 @@ let find_raise_label i =
(* Will the translation of l lead to a jump to label ? *)
let code_as_jump l sz = match l with
| Lstaticraise (i,[]) ->
- let label,size = find_raise_label i in
- if sz = size then
+ let label,size,tb = find_raise_label i in
+ if sz = size && tb == !try_blocks then
Some label
else
None
@@ -405,6 +411,7 @@ let comp_primitive p args =
| Pbigstring_set_64(_) -> Kccall("caml_ba_uint8_set64", 3)
| Pbswap16 -> Kccall("caml_bswap16", 1)
| Pbbswap(bi) -> comp_bint_primitive bi "bswap" args
+ | Pint_as_pointer -> Kccall("caml_int_as_pointer", 1)
| _ -> fatal_error "Bytegen.comp_primitive"
let is_immed n = immed_min <= n && n <= immed_max
@@ -640,8 +647,7 @@ let rec comp_expr env exp sz cont =
(comp_expr
(add_vars vars (sz+1) env)
handler (sz+nvars) (add_pop nvars cont1)) in
- sz_static_raises :=
- (i, (lbl_handler, sz+nvars)) :: !sz_static_raises ;
+ push_static_raise i lbl_handler (sz+nvars);
push_dummies nvars
(comp_expr env body (sz+nvars)
(add_pop nvars (branch1 :: cont2)))
@@ -652,30 +658,39 @@ let rec comp_expr env exp sz cont =
(Kpush::comp_expr
(add_var var (sz+1) env)
handler (sz+1) (add_pop 1 cont1)) in
- sz_static_raises :=
- (i, (lbl_handler, sz)) :: !sz_static_raises ;
+ push_static_raise i lbl_handler sz;
comp_expr env body sz (branch1 :: cont2)
end in
sz_static_raises := List.tl !sz_static_raises ;
r
| Lstaticraise (i, args) ->
let cont = discard_dead_code cont in
- let label,size = find_raise_label i in
+ let label,size,tb = find_raise_label i in
+ let cont = branch_to label cont in
+ let rec loop sz tbb =
+ if tb == tbb then add_pop (sz-size) cont
+ else match tbb with
+ | [] -> assert false
+ | try_sz :: tbb -> add_pop (sz-try_sz-4) (Kpoptrap :: loop try_sz tbb)
+ in
+ let cont = loop sz !try_blocks in
begin match args with
| [arg] -> (* optim, argument passed in accumulator *)
- comp_expr env arg sz
- (add_pop (sz-size) (branch_to label cont))
- | _ ->
- comp_exit_args env args sz size
- (add_pop (sz-size) (branch_to label cont))
+ comp_expr env arg sz cont
+ | _ -> comp_exit_args env args sz size cont
end
| Ltrywith(body, id, handler) ->
let (branch1, cont1) = make_branch cont in
let lbl_handler = new_label() in
- Kpushtrap lbl_handler ::
- comp_expr env body (sz+4) (Kpoptrap :: branch1 ::
- Klabel lbl_handler :: Kpush ::
- comp_expr (add_var id (sz+1) env) handler (sz+1) (add_pop 1 cont1))
+ let body_cont =
+ Kpoptrap :: branch1 ::
+ Klabel lbl_handler :: Kpush ::
+ comp_expr (add_var id (sz+1) env) handler (sz+1) (add_pop 1 cont1)
+ in
+ try_blocks := sz :: !try_blocks;
+ let l = comp_expr env body (sz+4) body_cont in
+ try_blocks := List.tl !try_blocks;
+ Kpushtrap lbl_handler :: l
| Lifthenelse(cond, ifso, ifnot) ->
comp_binary_test env cond ifso ifnot sz cont
| Lsequence(exp1, exp2) ->
@@ -919,3 +934,10 @@ let compile_phrase expr =
let init_code = comp_block empty_env expr 1 [Kreturn 1] in
let fun_code = comp_remainder [] in
(init_code, fun_code)
+
+let reset () =
+ label_counter := 0;
+ sz_static_raises := [];
+ compunit_name := "";
+ Stack.clear functions_to_compile;
+ max_stack_used := 0
diff --git a/bytecomp/bytegen.mli b/bytecomp/bytegen.mli
index 3c24cc8e86..24f1d64f32 100644
--- a/bytecomp/bytegen.mli
+++ b/bytecomp/bytegen.mli
@@ -17,3 +17,4 @@ open Instruct
val compile_implementation: string -> lambda -> instruction list
val compile_phrase: lambda -> instruction list * instruction list
+val reset: unit -> unit
diff --git a/bytecomp/bytelibrarian.ml b/bytecomp/bytelibrarian.ml
index c63cf80ec2..7c96dfd0e7 100644
--- a/bytecomp/bytelibrarian.ml
+++ b/bytecomp/bytelibrarian.ml
@@ -60,7 +60,7 @@ let copy_object_file ppf oc name =
raise(Error(File_not_found name)) in
let ic = open_in_bin file_name in
try
- let buffer = input_bytes ic (String.length cmo_magic_number) in
+ let buffer = really_input_string ic (String.length cmo_magic_number) in
if buffer = cmo_magic_number then begin
let compunit_pos = input_binary_int ic in
seek_in ic compunit_pos;
@@ -124,3 +124,8 @@ let () =
| Error err -> Some (Location.error_of_printer_file report_error err)
| _ -> None
)
+
+let reset () =
+ lib_ccobjs := [];
+ lib_ccopts := [];
+ lib_dllibs := []
diff --git a/bytecomp/bytelibrarian.mli b/bytecomp/bytelibrarian.mli
index 757874cb49..b9a4ced849 100644
--- a/bytecomp/bytelibrarian.mli
+++ b/bytecomp/bytelibrarian.mli
@@ -30,3 +30,5 @@ exception Error of error
open Format
val report_error: formatter -> error -> unit
+
+val reset: unit -> unit
diff --git a/bytecomp/bytelink.ml b/bytecomp/bytelink.ml
index 75db3533c9..c0f8f6a935 100644
--- a/bytecomp/bytelink.ml
+++ b/bytecomp/bytelink.ml
@@ -113,7 +113,7 @@ let scan_file obj_name tolink =
raise(Error(File_not_found obj_name)) in
let ic = open_in_bin file_name in
try
- let buffer = input_bytes ic (String.length cmo_magic_number) in
+ let buffer = really_input_string ic (String.length cmo_magic_number) in
if buffer = cmo_magic_number then begin
(* This is a .cmo file. It must be linked in any case.
Read the relocation information to see which modules it
@@ -158,15 +158,20 @@ let scan_file obj_name tolink =
(* Consistency check between interfaces *)
let crc_interfaces = Consistbl.create ()
+let interfaces = ref ([] : string list)
let implementations_defined = ref ([] : (string * string) list)
let check_consistency ppf file_name cu =
begin try
List.iter
- (fun (name, crc) ->
- if name = cu.cu_name
- then Consistbl.set crc_interfaces name crc file_name
- else Consistbl.check crc_interfaces name crc file_name)
+ (fun (name, crco) ->
+ interfaces := name :: !interfaces;
+ match crco with
+ None -> ()
+ | Some crc ->
+ if name = cu.cu_name
+ then Consistbl.set crc_interfaces name crc file_name
+ else Consistbl.check crc_interfaces name crc file_name)
cu.cu_imports
with Consistbl.Inconsistency(name, user, auth) ->
raise(Error(Inconsistent_import(name, user, auth)))
@@ -183,7 +188,11 @@ let check_consistency ppf file_name cu =
(cu.cu_name, file_name) :: !implementations_defined
let extract_crc_interfaces () =
- Consistbl.extract crc_interfaces
+ Consistbl.extract !interfaces crc_interfaces
+
+let clear_crc_interfaces () =
+ Consistbl.clear crc_interfaces;
+ interfaces := []
(* Record compilation events *)
@@ -256,7 +265,7 @@ let output_debug_info oc =
List.iter
(fun (ofs, evl) ->
output_binary_int oc ofs;
- Array.iter (output_string oc) evl)
+ Array.iter (output_bytes oc) evl)
!debug_info;
debug_info := []
@@ -307,7 +316,7 @@ let link_bytecode ppf tolink exec_name standalone =
(* The bytecode *)
let start_code = pos_out outchan in
Symtable.init();
- Consistbl.clear crc_interfaces;
+ 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
@@ -317,7 +326,7 @@ let link_bytecode ppf tolink exec_name standalone =
try Dll.open_dlls Dll.For_checking sharedobjs
with Failure reason -> raise(Error(Cannot_open_dll reason))
end;
- let output_fun = output_string outchan
+ 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();
@@ -371,12 +380,12 @@ let output_code_string_counter = ref 0
let output_code_string outchan code =
let pos = ref 0 in
- let len = String.length code in
+ let len = Bytes.length code in
while !pos < len do
- let c1 = Char.code(code.[!pos]) in
- let c2 = Char.code(code.[!pos + 1]) in
- let c3 = Char.code(code.[!pos + 2]) in
- let c4 = Char.code(code.[!pos + 3]) in
+ let c1 = Char.code(Bytes.get code !pos) in
+ let c2 = Char.code(Bytes.get code (!pos + 1)) in
+ let c3 = Char.code(Bytes.get code (!pos + 2)) in
+ let c4 = Char.code(Bytes.get code (!pos + 3)) in
pos := !pos + 4;
Printf.fprintf outchan "0x%02x%02x%02x%02x, " c4 c3 c2 c1;
incr output_code_string_counter;
@@ -440,11 +449,11 @@ let link_bytecode_as_c ppf tolink outfile =
\n char **argv);\n";
output_string outchan "static int caml_code[] = {\n";
Symtable.init();
- Consistbl.clear crc_interfaces;
+ clear_crc_interfaces ();
let currpos = ref 0 in
let output_fun code =
output_code_string outchan code;
- currpos := !currpos + String.length 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 *)
@@ -629,3 +638,13 @@ let () =
| Error err -> Some (Location.error_of_printer_file report_error err)
| _ -> None
)
+
+let reset () =
+ lib_ccobjs := [];
+ lib_ccopts := [];
+ lib_dllibs := [];
+ missing_globals := IdentSet.empty;
+ Consistbl.clear crc_interfaces;
+ implementations_defined := [];
+ debug_info := [];
+ output_code_string_counter := 0
diff --git a/bytecomp/bytelink.mli b/bytecomp/bytelink.mli
index 6e123c3f53..37dad2b526 100644
--- a/bytecomp/bytelink.mli
+++ b/bytecomp/bytelink.mli
@@ -13,11 +13,12 @@
(* Link .cmo files and produce a bytecode executable. *)
val link : Format.formatter -> string list -> string -> unit
+val reset : unit -> unit
val check_consistency:
Format.formatter -> string -> Cmo_format.compilation_unit -> unit
-val extract_crc_interfaces: unit -> (string * Digest.t) list
+val extract_crc_interfaces: unit -> (string * Digest.t option) list
type error =
File_not_found of string
diff --git a/bytecomp/bytepackager.ml b/bytecomp/bytepackager.ml
index 23582c1cb2..3348f46dcd 100644
--- a/bytecomp/bytepackager.ml
+++ b/bytecomp/bytepackager.ml
@@ -101,7 +101,9 @@ let read_member_info file = (
if Filename.check_suffix file ".cmo" then begin
let ic = open_in_bin file in
try
- let buffer = input_bytes ic (String.length Config.cmo_magic_number) in
+ let buffer =
+ really_input_string ic (String.length Config.cmo_magic_number)
+ in
if buffer <> Config.cmo_magic_number then
raise(Error(Not_an_object_file file));
let compunit_pos = input_binary_int ic in
@@ -233,7 +235,8 @@ let package_object_files ppf files targetfile targetname coercion =
cu_pos = pos_code;
cu_codesize = pos_debug - pos_code;
cu_reloc = List.rev !relocs;
- cu_imports = (targetname, Env.crc_of_unit targetname) :: imports;
+ cu_imports =
+ (targetname, Some (Env.crc_of_unit targetname)) :: imports;
cu_primitives = !primitives;
cu_force_link = !force_link;
cu_debug = if pos_final > pos_debug then pos_debug else 0;
@@ -248,7 +251,7 @@ let package_object_files ppf files targetfile targetname coercion =
(* The entry point *)
-let package_files ppf files targetfile =
+let package_files ppf initial_env files targetfile =
let files =
List.map
(fun f ->
@@ -259,11 +262,12 @@ let package_files ppf files targetfile =
let targetcmi = prefix ^ ".cmi" in
let targetname = String.capitalize(Filename.basename prefix) in
try
- let coercion = Typemod.package_units files targetcmi targetname in
- let ret = package_object_files ppf files targetfile targetname coercion in
- ret
- with x ->
- remove_file targetfile; raise x
+ let coercion =
+ Typemod.package_units initial_env files targetcmi targetname in
+ let ret = package_object_files ppf files targetfile targetname coercion in
+ ret
+ with x ->
+ remove_file targetfile; raise x
(* Error report *)
@@ -293,3 +297,9 @@ let () =
| Error err -> Some (Location.error_of_printer_file report_error err)
| _ -> None
)
+
+let reset () =
+ relocs := [];
+ events := [];
+ primitives := [];
+ force_link := false
diff --git a/bytecomp/bytepackager.mli b/bytecomp/bytepackager.mli
index 04de0726a2..69e3c77acb 100644
--- a/bytecomp/bytepackager.mli
+++ b/bytecomp/bytepackager.mli
@@ -13,7 +13,7 @@
(* "Package" a set of .cmo files into one .cmo file having the
original compilation units as sub-modules. *)
-val package_files: Format.formatter -> string list -> string -> unit
+val package_files: Format.formatter -> Env.t -> string list -> string -> unit
type error =
Forward_reference of string * Ident.t
@@ -25,3 +25,4 @@ type error =
exception Error of error
val report_error: Format.formatter -> error -> unit
+val reset: unit -> unit
diff --git a/bytecomp/bytesections.ml b/bytecomp/bytesections.ml
index 5af3bc5237..759bde3b29 100644
--- a/bytecomp/bytesections.ml
+++ b/bytecomp/bytesections.ml
@@ -46,12 +46,14 @@ let read_toc ic =
let pos_trailer = in_channel_length ic - 16 in
seek_in ic pos_trailer;
let num_sections = input_binary_int ic in
- let header = Misc.input_bytes ic (String.length Config.exec_magic_number) in
+ let header =
+ really_input_string ic (String.length Config.exec_magic_number)
+ in
if header <> Config.exec_magic_number then raise Bad_magic_number;
seek_in ic (pos_trailer - 8 * num_sections);
section_table := [];
for _i = 1 to num_sections do
- let name = Misc.input_bytes ic 4 in
+ let name = really_input_string ic 4 in
let len = input_binary_int ic in
section_table := (name, len) :: !section_table
done
@@ -77,7 +79,7 @@ let seek_section ic name =
(* Return the contents of a section, as a string *)
let read_section_string ic name =
- Misc.input_bytes ic (seek_section ic name)
+ really_input_string ic (seek_section ic name)
(* Return the contents of a section, as marshalled data *)
@@ -90,3 +92,7 @@ let read_section_struct ic name =
let pos_first_section ic =
in_channel_length ic - 16 - 8 * List.length !section_table -
List.fold_left (fun total (name, len) -> total + len) 0 !section_table
+
+let reset () =
+ section_table := [];
+ section_beginning := 0
diff --git a/bytecomp/bytesections.mli b/bytecomp/bytesections.mli
index b9639c1fac..12e679d73f 100644
--- a/bytecomp/bytesections.mli
+++ b/bytecomp/bytesections.mli
@@ -50,3 +50,5 @@ val read_section_struct: in_channel -> string -> 'a
val pos_first_section: in_channel -> int
(* Return the position of the beginning of the first section *)
+
+val reset: unit -> unit
diff --git a/bytecomp/cmo_format.mli b/bytecomp/cmo_format.mli
index abf4f1af32..0c0f08f080 100644
--- a/bytecomp/cmo_format.mli
+++ b/bytecomp/cmo_format.mli
@@ -27,7 +27,8 @@ type compilation_unit =
mutable cu_pos: int; (* Absolute position in file *)
cu_codesize: int; (* Size of code block *)
cu_reloc: (reloc_info * int) list; (* Relocation information *)
- cu_imports: (string * Digest.t) list; (* Names and CRC of intfs imported *)
+ cu_imports:
+ (string * Digest.t option) list; (* Names and CRC of intfs imported *)
cu_primitives: string list; (* Primitives declared inside *)
mutable cu_force_link: bool; (* Must be linked even if unref'ed *)
mutable cu_debug: int; (* Position of debugging info, or 0 *)
diff --git a/bytecomp/dll.ml b/bytecomp/dll.ml
index 5c62b9edc3..21688e08ee 100644
--- a/bytecomp/dll.ml
+++ b/bytecomp/dll.ml
@@ -173,3 +173,9 @@ let init_toplevel dllpath =
opened_dlls := Array.to_list (get_current_dlls());
names_of_opened_dlls := [];
linking_in_core := true
+
+let reset () =
+ search_path := [];
+ opened_dlls :=[];
+ names_of_opened_dlls := [];
+ linking_in_core := false
diff --git a/bytecomp/dll.mli b/bytecomp/dll.mli
index 975315e268..878ffb919e 100644
--- a/bytecomp/dll.mli
+++ b/bytecomp/dll.mli
@@ -59,3 +59,5 @@ val init_compile: bool -> unit
contents of ld.conf file). Take note of the DLLs that were opened
when starting the running program. *)
val init_toplevel: string -> unit
+
+val reset: unit -> unit
diff --git a/bytecomp/emitcode.ml b/bytecomp/emitcode.ml
index a56bf9175b..95b9a20f59 100644
--- a/bytecomp/emitcode.ml
+++ b/bytecomp/emitcode.ml
@@ -381,7 +381,7 @@ let to_file outchan unit_name code =
cu_pos = pos_code;
cu_codesize = !out_position;
cu_reloc = List.rev !reloc_info;
- cu_imports = Env.imported_units();
+ cu_imports = Env.imports();
cu_primitives = List.map Primitive.byte_name
!Translmod.primitive_declarations;
cu_force_link = false;
@@ -402,7 +402,7 @@ let to_memory init_code fun_code =
emit init_code;
emit fun_code;
let code = Meta.static_alloc !out_position in
- LongString.unsafe_blit_to_string !out_buffer 0 code 0 !out_position;
+ LongString.unsafe_blit_to_bytes !out_buffer 0 code 0 !out_position;
let reloc = List.rev !reloc_info
and code_size = !out_position in
init();
@@ -417,3 +417,9 @@ let to_packed_file outchan code =
let reloc = !reloc_info in
init();
reloc
+
+let reset () =
+ out_buffer := LongString.create 1024;
+ out_position := 0;
+ label_table := [| |];
+ reloc_info := []
diff --git a/bytecomp/emitcode.mli b/bytecomp/emitcode.mli
index 60d791434a..ee0bccbf0d 100644
--- a/bytecomp/emitcode.mli
+++ b/bytecomp/emitcode.mli
@@ -21,7 +21,7 @@ val to_file: out_channel -> string -> instruction list -> unit
name of compilation unit implemented
list of instructions to emit *)
val to_memory: instruction list -> instruction list ->
- string * int * (reloc_info * int) list
+ bytes * int * (reloc_info * int) list
(* Arguments:
initialization code (terminated by STOP)
function code
@@ -36,3 +36,5 @@ val to_packed_file:
list of instructions to emit
Result:
relocation information (reversed) *)
+
+val reset: unit -> unit
diff --git a/bytecomp/lambda.ml b/bytecomp/lambda.ml
index f68588090b..3c1aaf26bb 100644
--- a/bytecomp/lambda.ml
+++ b/bytecomp/lambda.ml
@@ -121,6 +121,8 @@ type primitive =
(* byte swap *)
| Pbswap16
| Pbbswap of boxed_integer
+ (* Integer to external pointer *)
+ | Pint_as_pointer
and comparison =
Ceq | Cneq | Clt | Cgt | Cle | Cge
@@ -209,16 +211,23 @@ let const_unit = Const_pointer 0
let lambda_unit = Lconst const_unit
+(* Build sharing keys *)
+(*
+ Those keys are later compared with Pervasives.compare.
+ For that reason, they should not include cycles.
+*)
+
exception Not_simple
let max_raw = 32
let make_key e =
- let count = ref 0
+ let count = ref 0 (* Used for controling size *)
and make_key = Ident.make_key_generator () in
+ (* make_key is used for normalizing let-bound variables *)
let rec tr_rec env e =
incr count ;
- if !count > max_raw then raise Not_simple ;
+ if !count > max_raw then raise Not_simple ; (* Too big ! *)
match e with
| Lvar id ->
begin
@@ -262,11 +271,12 @@ let make_key e =
Lassign (x,tr_rec env e)
| Lsend (m,e1,e2,es,loc) ->
Lsend (m,tr_rec env e1,tr_rec env e2,tr_recs env es,Location.none)
- | Levent (e,evt) ->
- Levent (tr_rec env e,evt)
| Lifused (id,e) -> Lifused (id,tr_rec env e)
| Lletrec _|Lfunction _
- | Lfor _ | Lwhile _ ->
+ | Lfor _ | Lwhile _
+(* Beware: (PR#6412) the event argument to Levent
+ may include cyclic structure of type Type.typexpr *)
+ | Levent _ ->
raise Not_simple
and tr_recs env es = List.map (tr_rec env) es
@@ -399,6 +409,12 @@ let next_raise_count () =
incr raise_count ;
!raise_count
+let negative_raise_count = ref 0
+
+let next_negative_raise_count () =
+ decr negative_raise_count ;
+ !negative_raise_count
+
(* Anticipated staticraise, for guards *)
let staticfail = Lstaticraise (0,[])
@@ -529,3 +545,7 @@ let lam_of_loc kind loc =
file lnum cnum enum in
Lconst (Const_immstring loc)
| Loc_LINE -> Lconst (Const_base (Const_int lnum))
+
+let reset () =
+ raise_count := 0
+
diff --git a/bytecomp/lambda.mli b/bytecomp/lambda.mli
index 8acb4cd03e..2448087da7 100644
--- a/bytecomp/lambda.mli
+++ b/bytecomp/lambda.mli
@@ -121,6 +121,8 @@ type primitive =
(* byte swap *)
| Pbswap16
| Pbbswap of boxed_integer
+ (* Integer to external pointer *)
+ | Pint_as_pointer
and comparison =
Ceq | Cneq | Clt | Cgt | Cle | Cge
@@ -244,7 +246,10 @@ val negate_comparison : comparison -> comparison
(* Get a new static failure ident *)
val next_raise_count : unit -> int
-
+val next_negative_raise_count : unit -> int
+ (* Negative raise counts are used to compile 'match ... with exception x -> ...'.
+ This disabled some simplifications performed by the Simplif module that assume
+ that static raises are in tail position in their handler. *)
val staticfail : lambda (* Anticipated static failure *)
@@ -254,3 +259,5 @@ val patch_guarded : lambda -> lambda -> lambda
val raise_kind: raise_kind -> string
val lam_of_loc : loc_kind -> Location.t -> lambda
+
+val reset: unit -> unit
diff --git a/bytecomp/matching.ml b/bytecomp/matching.ml
index b1036ec9a5..5a8f71efcd 100644
--- a/bytecomp/matching.ml
+++ b/bytecomp/matching.ml
@@ -169,7 +169,7 @@ let ctx_matcher p =
match p.pat_desc with
| Tpat_construct (_, cstr,omegas) ->
begin match cstr.cstr_tag with
- | Cstr_exception _ -> (* exception matching *)
+ | Cstr_extension _ ->
let nargs = List.length omegas in
(fun q rem -> match q.pat_desc with
| Tpat_construct (_, cstr',args)
@@ -531,15 +531,14 @@ let up_ok_action act1 act2 =
try
let raw1 = tr_raw act1
and raw2 = tr_raw act2 in
- match raw1, raw2 with
- | Lstaticraise (i1,[]), Lstaticraise (i2,[]) -> i1=i2
- | _,_ -> raw1 = raw2
+ raw1 = raw2
with
| Exit -> false
-(* Nothing is kown about exception patterns, because of potential rebind *)
+(* Nothing is kown about exception/extension patterns,
+ because of potential rebind *)
let rec exc_inside p = match p.pat_desc with
- | Tpat_construct (_,{cstr_tag=Cstr_exception _},_) -> true
+ | Tpat_construct (_,{cstr_tag=Cstr_extension _},_) -> true
| Tpat_any|Tpat_constant _|Tpat_var _
| Tpat_construct (_,_,[])
| Tpat_variant (_,None,_)
@@ -661,7 +660,7 @@ let rec what_is_cases cases = match cases with
(* A few operation on default environments *)
let as_matrix cases = get_mins le_pats (List.map (fun (ps,_) -> ps) cases)
-(* For exception matching, record no imformation in matrix *)
+(* For extension matching, record no imformation in matrix *)
let as_matrix_omega cases =
get_mins le_pats
(List.map
@@ -937,9 +936,8 @@ let rec split_or argo cls args def =
do_split [] [] [] cls
-(* Ultra-naive spliting, close to semantics,
- used for exception, as potential rebind prevents any kind of
- optimisation *)
+(* Ultra-naive spliting, close to semantics, used for extension,
+ as potential rebind prevents any kind of optimisation *)
and split_naive cls args def k =
@@ -1004,7 +1002,7 @@ and split_constr cls args def k =
let ex_pat = what_is_cases cls in
match ex_pat.pat_desc with
| Tpat_any -> precompile_var args cls def k
- | Tpat_construct (_,{cstr_tag=Cstr_exception _},_) ->
+ | Tpat_construct (_,{cstr_tag=Cstr_extension _},_) ->
split_naive cls args def k
| _ ->
@@ -1114,7 +1112,7 @@ and dont_precompile_var args cls def k =
and is_exc p = match p.pat_desc with
| Tpat_or (p1,p2,_) -> is_exc p1 || is_exc p2
| Tpat_alias (p,v,_) -> is_exc p
-| Tpat_construct (_,{cstr_tag = Cstr_exception _},_) -> true
+| Tpat_construct (_,{cstr_tag=Cstr_extension _},_) -> true
| _ -> false
and precompile_or argo cls ors args def k = match ors with
@@ -1355,7 +1353,7 @@ let make_constr_matching p def ctx = function
else match cstr.cstr_tag with
Cstr_constant _ | Cstr_block _ ->
make_field_args Alias arg 0 (cstr.cstr_arity - 1) argl
- | Cstr_exception _ ->
+ | Cstr_extension _ ->
make_field_args Alias arg 1 cstr.cstr_arity argl in
{pm=
{cases = []; args = newargs;
@@ -1486,7 +1484,7 @@ 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 in
+ let env = Env.open_pers_signature modname Env.initial_safe_string in
let p = try
match Env.lookup_value (Longident.Lident field) env with
| (Path.Pdot(_,_,i), _) -> i
@@ -1634,7 +1632,7 @@ let make_record_matching all_labels def = function
match lbl.lbl_repres with
Record_regular | Record_inlined _ -> Pfield lbl.lbl_pos
| Record_float -> Pfloatfield lbl.lbl_pos
- | Record_exception _ -> Pfield (lbl.lbl_pos + 1)
+ | Record_extension _ -> Pfield (lbl.lbl_pos + 1)
in
let str =
match lbl.lbl_mut with
@@ -2365,39 +2363,61 @@ let split_cases tag_lambda_list =
sort_int_lambda_list const,
sort_int_lambda_list nonconst
+let split_extension_cases tag_lambda_list =
+ let rec split_rec = function
+ [] -> ([], [])
+ | (cstr, act) :: rem ->
+ let (consts, nonconsts) = split_rec rem in
+ match cstr with
+ Cstr_extension(path, true) -> ((path, act) :: consts, nonconsts)
+ | Cstr_extension(path, false) -> (consts, (path, act) :: nonconsts)
+ | _ -> assert false in
+ split_rec tag_lambda_list
+
let combine_constructor arg ex_pat cstr partial ctx def
(tag_lambda_list, total1, pats) =
if cstr.cstr_consts < 0 then begin
- (* Special cases for exceptions *)
+ (* Special cases for extensions *)
let fail, to_add, local_jumps =
mk_failaction_neg partial ctx def in
let tag_lambda_list = to_add@tag_lambda_list in
let lambda1 =
- let default, tests =
+ let consts, nonconsts = split_extension_cases tag_lambda_list in
+ let default, consts, nonconsts =
match fail with
| None ->
- begin match tag_lambda_list with
- | (_, act)::rem -> act,rem
+ begin match consts, nonconsts with
+ | _, (_, act)::rem -> act, consts, rem
+ | (_, act)::rem, _ -> act, rem, nonconsts
| _ -> assert false
end
- | Some fail -> fail, tag_lambda_list in
- List.fold_right
- (fun (ex, act) rem ->
- assert(ex = cstr.cstr_tag);
- match ex with
- | Cstr_exception (path, _) ->
- let slot =
- if cstr.cstr_arity = 0 then arg
- else Lprim(Pfield 0, [arg])
- in
- Lifthenelse(Lprim(Pintcomp Ceq,
- [slot;
- transl_path ~loc:ex_pat.pat_loc
- ex_pat.pat_env path]),
- act, rem)
- | _ -> assert false)
- tests default in
+ | Some fail -> fail, consts, nonconsts in
+ let nonconst_lambda =
+ match nonconsts with
+ [] -> default
+ | _ ->
+ let tag = Ident.create "tag" in
+ let tests =
+ List.fold_right
+ (fun (path, act) rem ->
+ Lifthenelse(Lprim(Pintcomp Ceq,
+ [Lvar tag;
+ transl_path ex_pat.pat_env path]),
+ act, rem))
+ nonconsts
+ default
+ in
+ Llet(Alias, tag, Lprim(Pfield 0, [arg]), tests)
+ in
+ List.fold_right
+ (fun (path, act) rem ->
+ Lifthenelse(Lprim(Pintcomp Ceq,
+ [arg; transl_path ex_pat.pat_env path]),
+ act, rem))
+ consts
+ nonconst_lambda
+ in
lambda1, jumps_union local_jumps total1
end else begin
(* Regular concrete type *)
diff --git a/bytecomp/meta.ml b/bytecomp/meta.ml
index 35d8776666..f7711ff15e 100644
--- a/bytecomp/meta.ml
+++ b/bytecomp/meta.ml
@@ -12,13 +12,13 @@
external global_data : unit -> Obj.t array = "caml_get_global_data"
external realloc_global_data : int -> unit = "caml_realloc_global"
-external static_alloc : int -> string = "caml_static_alloc"
-external static_free : string -> unit = "caml_static_free"
-external static_resize : string -> int -> string = "caml_static_resize"
-external static_release_bytecode : string -> int -> unit
+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 : string -> int -> closure = "caml_reify_bytecode"
+external reify_bytecode : bytes -> int -> closure = "caml_reify_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
diff --git a/bytecomp/meta.mli b/bytecomp/meta.mli
index a8ef5272aa..cb3565dcc8 100644
--- a/bytecomp/meta.mli
+++ b/bytecomp/meta.mli
@@ -14,13 +14,13 @@
external global_data : unit -> Obj.t array = "caml_get_global_data"
external realloc_global_data : int -> unit = "caml_realloc_global"
-external static_alloc : int -> string = "caml_static_alloc"
-external static_free : string -> unit = "caml_static_free"
-external static_release_bytecode : string -> int -> unit
+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 : string -> int -> string = "caml_static_resize"
+external static_resize : bytes -> int -> bytes = "caml_static_resize"
type closure = unit -> Obj.t
-external reify_bytecode : string -> int -> closure = "caml_reify_bytecode"
+external reify_bytecode : bytes -> int -> closure = "caml_reify_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
diff --git a/bytecomp/printlambda.ml b/bytecomp/printlambda.ml
index 006c8e2798..12985c53c0 100644
--- a/bytecomp/printlambda.ml
+++ b/bytecomp/printlambda.ml
@@ -86,7 +86,7 @@ let record_rep ppf r =
| Record_regular -> fprintf ppf "regular"
| Record_inlined i -> fprintf ppf "inlined(%i)" i
| Record_float -> fprintf ppf "float"
- | Record_exception p -> fprintf ppf "exn (%s)" (Path.name p)
+ | Record_extension p -> fprintf ppf "ext (%s)" (Path.name p)
;;
let string_of_loc_kind = function
@@ -239,6 +239,7 @@ let primitive ppf = function
else fprintf ppf "bigarray.array1.set64"
| Pbswap16 -> fprintf ppf "bswap16"
| Pbbswap(bi) -> print_boxed_integer "bswap" ppf bi
+ | Pint_as_pointer -> fprintf ppf "int_as_pointer"
let rec lam ppf = function
| Lvar id ->
diff --git a/bytecomp/simplif.ml b/bytecomp/simplif.ml
index 85f0d71f9d..fd3d21c173 100644
--- a/bytecomp/simplif.ml
+++ b/bytecomp/simplif.ml
@@ -256,7 +256,7 @@ let simplify_exits lam =
| Lstaticcatch (l1,(i,xs),l2) ->
begin match count_exit i with
| 0 -> simplif l1
- | 1 ->
+ | 1 when i >= 0 ->
Hashtbl.add subst i (xs,simplif l2) ;
simplif l1
| _ ->
diff --git a/bytecomp/symtable.ml b/bytecomp/symtable.ml
index baff51c486..37609d7751 100644
--- a/bytecomp/symtable.ml
+++ b/bytecomp/symtable.ml
@@ -198,7 +198,7 @@ let gen_patch_object str_set buff patchlist =
gen_patch_int str_set buff pos (num_of_prim name))
patchlist
-let patch_object = gen_patch_object String.unsafe_set
+let patch_object = gen_patch_object Bytes.unsafe_set
let ls_patch_object = gen_patch_object LongString.set
(* Translate structured constants *)
@@ -300,7 +300,7 @@ let init_toplevel () =
Dll.init_toplevel dllpath;
(* Recover CRC infos for interfaces *)
let crcintfs =
- try (Obj.magic (sect.read_struct "CRCS") : (string * Digest.t) list)
+ try (Obj.magic (sect.read_struct "CRCS") : (string * Digest.t option) list)
with Not_found -> [] in
(* Done *)
sect.close_reader();
@@ -383,3 +383,8 @@ let () =
| Error err -> Some (Location.error_of_printer_file report_error err)
| _ -> None
)
+
+let reset () =
+ global_table := empty_numtable;
+ literal_table := [];
+ c_prim_table := empty_numtable
diff --git a/bytecomp/symtable.mli b/bytecomp/symtable.mli
index e3c33d2396..ffc878bf10 100644
--- a/bytecomp/symtable.mli
+++ b/bytecomp/symtable.mli
@@ -17,7 +17,7 @@ open Cmo_format
(* Functions for batch linking *)
val init: unit -> unit
-val patch_object: string -> (reloc_info * int) list -> unit
+val patch_object: bytes -> (reloc_info * int) list -> unit
val ls_patch_object: Misc.LongString.t -> (reloc_info * int) list -> unit
val require_primitive: string -> unit
val initial_global_table: unit -> Obj.t array
@@ -29,7 +29,7 @@ val data_primitive_names: unit -> string
(* Functions for the toplevel *)
-val init_toplevel: unit -> (string * Digest.t) list
+val init_toplevel: unit -> (string * Digest.t option) list
val update_global_table: unit -> unit
val get_global_value: Ident.t -> Obj.t
val is_global_defined: Ident.t -> bool
@@ -57,3 +57,5 @@ exception Error of error
open Format
val report_error: formatter -> error -> unit
+
+val reset: unit -> unit
diff --git a/bytecomp/translclass.ml b/bytecomp/translclass.ml
index 72022a5e3a..2363bd8fb6 100644
--- a/bytecomp/translclass.ml
+++ b/bytecomp/translclass.ml
@@ -145,7 +145,7 @@ let rec build_object_init cl_table obj params inh_init obj_init cl =
| Tcf_val (_, _, id, Tcfk_concrete (_, exp), _) ->
(inh_init, lsequence (set_inst_var obj id exp) obj_init,
has_init)
- | Tcf_method _ | Tcf_val _ | Tcf_constraint _ ->
+ | Tcf_method _ | Tcf_val _ | Tcf_constraint _ | Tcf_attribute _ ->
(inh_init, obj_init, has_init)
| Tcf_initializer _ ->
(inh_init, obj_init, true)
@@ -305,7 +305,9 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
Lsequence(mkappl (oo_prim "add_initializer",
Lvar cla :: msubst false (transl_exp exp)),
cl_init),
- methods, values))
+ methods, values)
+ | Tcf_attribute _ ->
+ (inh_init, cl_init, methods, values))
str.cstr_fields
(inh_init, cl_init, [], [])
in
@@ -810,7 +812,7 @@ let transl_class ids cl_id pub_meths cl vflag =
(*
let cl_id = ci.ci_id_class in
(* TODO: cl_id is used somewhere else as typesharp ? *)
- let _arity = List.length (fst ci.ci_params) in
+ let _arity = List.length ci.ci_params in
let pub_meths = m in
let cl = ci.ci_expr in
let vflag = vf in
diff --git a/bytecomp/translcore.ml b/bytecomp/translcore.ml
index 0df2c9ce2d..f21f8c071e 100644
--- a/bytecomp/translcore.ml
+++ b/bytecomp/translcore.ml
@@ -311,6 +311,7 @@ let primitives_table = create_hashtable 57 [
"%bswap_int32", Pbbswap(Pint32);
"%bswap_int64", Pbbswap(Pint64);
"%bswap_native", Pbbswap(Pnativeint);
+ "%int_as_pointer", Pint_as_pointer;
]
let prim_makearray =
@@ -553,7 +554,7 @@ let rec push_defaults loc bindings cases partial =
val_attributes = [];
Types.val_loc = Location.none;
})},
- cases, partial) }
+ cases, [], partial) }
in
push_defaults loc bindings
[{c_lhs={pat with pat_desc = Tpat_var (param, mknoloc name)};
@@ -730,12 +731,8 @@ and transl_exp0 e =
end
| Texp_apply(funct, oargs) ->
event_after e (transl_apply (transl_exp funct) oargs e.exp_loc)
- | Texp_match({exp_desc = Texp_tuple argl}, pat_expr_list, partial) ->
- Matching.for_multiple_match e.exp_loc
- (transl_list argl) (transl_cases pat_expr_list) partial
- | Texp_match(arg, pat_expr_list, partial) ->
- Matching.for_function e.exp_loc None
- (transl_exp arg) (transl_cases pat_expr_list) partial
+ | Texp_match(arg, pat_expr_list, exn_pat_expr_list, partial) ->
+ transl_match e arg pat_expr_list exn_pat_expr_list partial
| Texp_try(body, pat_expr_list) ->
let id = name_pattern "exn" pat_expr_list in
Ltrywith(transl_exp body, id,
@@ -761,10 +758,12 @@ and transl_exp0 e =
with Not_constant ->
Lprim(Pmakeblock(n, Immutable), ll)
end
- | Cstr_exception (path, _) ->
- let slot = transl_path ~loc:e.exp_loc e.exp_env path in
- if cstr.cstr_arity = 0 then slot
- else Lprim(Pmakeblock(0, Immutable), slot :: ll)
+ | Cstr_extension(path, is_const) ->
+ if is_const then
+ transl_path e.exp_env path
+ else
+ Lprim(Pmakeblock(0, Immutable),
+ transl_path e.exp_env path :: ll)
end
| Texp_variant(l, arg) ->
let tag = Btype.hash_variant l in
@@ -789,7 +788,7 @@ and transl_exp0 e =
match lbl.lbl_repres with
Record_regular | Record_inlined _ -> Pfield lbl.lbl_pos
| Record_float -> Pfloatfield lbl.lbl_pos
- | Record_exception _ -> Pfield (lbl.lbl_pos + 1)
+ | Record_extension _ -> Pfield (lbl.lbl_pos + 1)
in
Lprim(access, [transl_exp arg])
| Texp_setfield(arg, _, lbl, newval) ->
@@ -798,7 +797,7 @@ and transl_exp0 e =
Record_regular
| Record_inlined _ -> Psetfield(lbl.lbl_pos, maybe_pointer newval)
| Record_float -> Psetfloatfield lbl.lbl_pos
- | Record_exception _ ->
+ | Record_extension _ ->
Psetfield (lbl.lbl_pos + 1, maybe_pointer newval)
in
Lprim(access, [transl_exp arg; transl_exp newval])
@@ -912,7 +911,6 @@ and transl_exp0 e =
|| has_base_type e Predef.path_exn
|| has_base_type e Predef.path_array
|| has_base_type e Predef.path_list
- || has_base_type e Predef.path_format6
|| has_base_type e Predef.path_option
|| has_base_type e Predef.path_nativeint
|| has_base_type e Predef.path_int32
@@ -1099,7 +1097,7 @@ and transl_record env all_labels repres lbl_expr_list opt_init_expr =
let access =
match all_labels.(i).lbl_repres with
Record_regular | Record_inlined _ -> Pfield i
- | Record_exception _ -> Pfield (i + 1)
+ | Record_extension _ -> Pfield (i + 1)
| Record_float -> Pfloatfield i in
lv.(i) <- Lprim(access, [Lvar init_id])
done
@@ -1121,14 +1119,14 @@ and transl_record env all_labels repres lbl_expr_list opt_init_expr =
| Record_inlined tag -> Lconst(Const_block(tag, cl))
| Record_float ->
Lconst(Const_float_array(List.map extract_float cl))
- | Record_exception _ ->
+ | Record_extension _ ->
raise Not_constant
with Not_constant ->
match repres with
Record_regular -> Lprim(Pmakeblock(0, mut), ll)
| Record_inlined tag -> Lprim(Pmakeblock(tag, mut), ll)
| Record_float -> Lprim(Pmakearray Pfloatarray, ll)
- | Record_exception path ->
+ | Record_extension path ->
let slot = transl_path env path in
Lprim(Pmakeblock(0, Immutable), slot :: ll)
in
@@ -1148,7 +1146,7 @@ and transl_record env all_labels repres lbl_expr_list opt_init_expr =
Record_regular
| Record_inlined _ -> Psetfield(lbl.lbl_pos, maybe_pointer expr)
| Record_float -> Psetfloatfield lbl.lbl_pos
- | Record_exception _ -> Psetfield(lbl.lbl_pos + 1, maybe_pointer expr)
+ | Record_extension _ -> Psetfield(lbl.lbl_pos + 1, maybe_pointer expr)
in
Lsequence(Lprim(upd, [Lvar copy_id; transl_exp expr]), cont) in
begin match opt_init_expr with
@@ -1160,6 +1158,34 @@ and transl_record env all_labels repres lbl_expr_list opt_init_expr =
end
end
+and transl_match e arg pat_expr_list exn_pat_expr_list partial =
+ let id = name_pattern "exn" exn_pat_expr_list
+ and cases = transl_cases pat_expr_list
+ and exn_cases = transl_cases exn_pat_expr_list in
+ let static_catch body val_ids handler =
+ let static_exception_id = next_negative_raise_count () in
+ Lstaticcatch
+ (Ltrywith (Lstaticraise (static_exception_id, body), id,
+ Matching.for_trywith (Lvar id) exn_cases),
+ (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 _ -> 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 = 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)
+
+
(* Wrapper for class compilation *)
(*
diff --git a/bytecomp/translmod.ml b/bytecomp/translmod.ml
index 64964e187d..01ca31caf3 100644
--- a/bytecomp/translmod.ml
+++ b/bytecomp/translmod.ml
@@ -30,23 +30,50 @@ type error =
exception Error of Location.t * error
-(* Compile an exception definition *)
+(* Keep track of the root path (from the root of the namespace to the
+ currently compiled module expression). Useful for naming extensions. *)
+
+let global_path glob = Some(Pident glob)
+let functor_path path param =
+ match path with
+ None -> None
+ | Some p -> Some(Papply(p, Pident param))
+let field_path path field =
+ match path with
+ None -> None
+ | Some p -> Some(Pdot(p, Ident.name field, Path.nopos))
+
+(* Compile type extensions *)
let prim_set_oo_id =
Pccall {Primitive.prim_name = "caml_set_oo_id"; prim_arity = 1;
prim_alloc = false; prim_native_name = "";
prim_native_float = false}
-let transl_exception path decl =
+let transl_extension_constructor env path ext =
let name =
match path with
- None -> Ident.name decl.cd_id
+ None -> Ident.name ext.ext_id
| Some p -> Path.name p
in
- Lprim(prim_set_oo_id,
- [Lprim(Pmakeblock(Obj.object_tag, Mutable),
- [Lconst(Const_base(Const_string (name,None)));
- Lconst(Const_base(Const_int 0))])])
+ match ext.ext_kind with
+ Text_decl(args, ret) ->
+ Lprim(prim_set_oo_id,
+ [Lprim(Pmakeblock(Obj.object_tag, Mutable),
+ [Lconst(Const_base(Const_string (name,None)));
+ Lconst(Const_base(Const_int 0))])])
+ | Text_rebind(path, lid) ->
+ transl_path ~loc:ext.ext_loc env path
+
+let transl_type_extension env rootpath tyext body =
+ List.fold_right
+ (fun ext body ->
+ let lam =
+ transl_extension_constructor env (field_path rootpath ext.ext_id) ext
+ in
+ Llet(Strict, ext.ext_id, lam, body))
+ tyext.tyext_constructors
+ body
(* Compile a coercion *)
@@ -126,19 +153,6 @@ let record_primitive = function
primitive_declarations := p :: !primitive_declarations
| _ -> ()
-(* Keep track of the root path (from the root of the namespace to the
- currently compiled module expression). Useful for naming exceptions. *)
-
-let global_path glob = Some(Pident glob)
-let functor_path path param =
- match path with
- None -> None
- | Some p -> Some(Papply(p, Pident param))
-let field_path path field =
- match path with
- None -> None
- | Some p -> Some(Pdot(p, Ident.name field, Path.nopos))
-
(* Utilities for compiling "module rec" definitions *)
let mod_prim name =
@@ -181,7 +195,7 @@ let init_shape modl =
init_v :: init_shape_struct env rem
| Sig_type(id, tdecl, _) :: rem ->
init_shape_struct (Env.add_type ~check:false id tdecl env) rem
- | Sig_exception(id, edecl) :: rem ->
+ | Sig_typext(id, ext, _) :: rem ->
raise Not_found
| Sig_module(id, md, _) :: rem ->
init_shape_mod env md.md_type ::
@@ -275,14 +289,14 @@ let compile_recmodule compile_rhs 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, exceptions, modules, classes.
+ 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_exception(id, decl) :: rem -> id :: bound_value_identifiers rem
+ | Sig_typext(id, ext, _) :: rem -> id :: bound_value_identifiers rem
| Sig_module(id, mty, _) :: rem -> id :: bound_value_identifiers rem
| Sig_class(id, decl, _) :: rem -> id :: bound_value_identifiers rem
| _ :: rem -> bound_value_identifiers rem
@@ -363,14 +377,14 @@ and transl_structure fields cc rootpath = function
transl_structure fields cc rootpath rem
| Tstr_type(decls) ->
transl_structure fields cc rootpath rem
- | Tstr_exception decl ->
- let id = decl.cd_id in
- Llet(Strict, id, transl_exception (field_path rootpath id) decl,
- transl_structure (id :: fields) cc rootpath rem)
- | Tstr_exn_rebind er ->
- let id = er.exrb_id in
- let loc = er.exrb_txt.Location.loc in
- Llet(Strict, id, transl_path ~loc item.str_env er.exrb_path,
+ | Tstr_typext(tyext) ->
+ let ids = List.map (fun ext -> ext.ext_id) tyext.tyext_constructors in
+ transl_type_extension item.str_env rootpath tyext
+ (transl_structure (List.rev_append ids fields) cc rootpath rem)
+ | Tstr_exception ext ->
+ let id = ext.ext_id in
+ let path = field_path rootpath id in
+ Llet(Strict, id, transl_extension_constructor item.str_env path ext,
transl_structure (id :: fields) cc rootpath rem)
| Tstr_module mb ->
let id = mb.mb_id in
@@ -394,7 +408,7 @@ and transl_structure fields cc rootpath = function
let cl = ci.ci_expr in
(id, transl_class ids id meths cl vf ))
cl_list,
- transl_structure (List.rev ids @ fields) cc rootpath rem)
+ transl_structure (List.rev_append ids fields) cc rootpath rem)
| Tstr_include incl ->
let ids = bound_value_identifiers incl.incl_type in
let modl = incl.incl_mod in
@@ -447,8 +461,10 @@ let rec defined_idents = function
let_bound_idents pat_expr_list @ defined_idents rem
| Tstr_primitive desc -> defined_idents rem
| Tstr_type decls -> defined_idents rem
- | Tstr_exception decl -> decl.cd_id :: defined_idents rem
- | Tstr_exn_rebind er -> er.exrb_id :: defined_idents rem
+ | 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_recmodule decls ->
List.map (fun mb -> mb.mb_id) decls @ defined_idents rem
@@ -471,8 +487,8 @@ let rec more_idents = function
| Tstr_value(rec_flag, pat_expr_list) -> more_idents rem
| Tstr_primitive _ -> more_idents rem
| Tstr_type decls -> more_idents rem
+ | Tstr_typext tyext -> more_idents rem
| Tstr_exception _ -> more_idents rem
- | Tstr_exn_rebind _ -> more_idents rem
| Tstr_recmodule decls -> more_idents rem
| Tstr_modtype _ -> more_idents rem
| Tstr_open _ -> more_idents rem
@@ -493,8 +509,10 @@ and all_idents = function
let_bound_idents pat_expr_list @ all_idents rem
| Tstr_primitive _ -> all_idents rem
| Tstr_type decls -> all_idents rem
- | Tstr_exception decl -> decl.cd_id :: all_idents rem
- | Tstr_exn_rebind er -> er.exrb_id :: all_idents rem
+ | 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_recmodule decls ->
List.map (fun mb -> mb.mb_id) decls @ all_idents rem
| Tstr_modtype _ -> all_idents rem
@@ -550,18 +568,18 @@ let transl_store_structure glob map prims str =
transl_store rootpath subst rem
| Tstr_type(decls) ->
transl_store rootpath subst rem
- | Tstr_exception decl ->
- let id = decl.cd_id in
- let lam = transl_exception (field_path rootpath id) decl in
- Lsequence(Llet(Strict, id, lam, store_ident id),
- transl_store rootpath (add_ident false id subst) rem)
- | Tstr_exn_rebind er ->
- let id = er.exrb_id in
- let loc = er.exrb_txt.Location.loc in
+ | Tstr_typext(tyext) ->
+ let ids = List.map (fun ext -> ext.ext_id) tyext.tyext_constructors in
let lam =
- subst_lambda subst (transl_path ~loc item.str_env er.exrb_path)
+ transl_type_extension item.str_env rootpath tyext (store_idents ids)
in
- Lsequence(Llet(Strict, id, lam, store_ident id),
+ Lsequence(subst_lambda subst lam,
+ transl_store rootpath (add_idents false ids subst) rem)
+ | Tstr_exception ext ->
+ let id = ext.ext_id in
+ let path = field_path rootpath id in
+ let lam = transl_extension_constructor item.str_env path ext in
+ Lsequence(Llet(Strict, id, subst_lambda subst lam, store_ident id),
transl_store rootpath (add_ident false id subst) rem)
| Tstr_module{mb_id=id; mb_expr={mod_desc = Tmod_structure str}} ->
let lam = transl_store (field_path rootpath id) subst str.str_items in
@@ -770,12 +788,15 @@ let transl_toplevel_item item =
let idents = let_bound_idents pat_expr_list in
transl_let rec_flag pat_expr_list
(make_sequence toploop_setvalue_id idents)
- | Tstr_exception decl ->
- toploop_setvalue decl.cd_id (transl_exception None decl)
- | Tstr_exn_rebind er ->
- let id = er.exrb_id in
- let loc = er.exrb_txt.Location.loc in
- toploop_setvalue id (transl_path ~loc item.str_env er.exrb_path)
+ | Tstr_typext(tyext) ->
+ let idents =
+ List.map (fun ext -> ext.ext_id) tyext.tyext_constructors
+ in
+ transl_type_extension item.str_env None tyext
+ (make_sequence toploop_setvalue_id idents)
+ | Tstr_exception ext ->
+ toploop_setvalue ext.ext_id
+ (transl_extension_constructor item.str_env None ext)
| Tstr_module {mb_id=id; mb_expr=modl} ->
(* we need to use the unique name for the module because of issues
with "open" (PR#1672) *)
@@ -913,3 +934,9 @@ let () =
| _ ->
None
)
+
+let reset () =
+ primitive_declarations := [];
+ transl_store_subst := Ident.empty;
+ toploop_ident.Ident.flags <- 0;
+ aliased_idents := Ident.empty
diff --git a/bytecomp/translmod.mli b/bytecomp/translmod.mli
index 8e5005546f..1d84aaabd2 100644
--- a/bytecomp/translmod.mli
+++ b/bytecomp/translmod.mli
@@ -37,3 +37,5 @@ type error =
exception Error of Location.t * error
val report_error: Format.formatter -> error -> unit
+
+val reset: unit -> unit
diff --git a/bytecomp/translobj.ml b/bytecomp/translobj.ml
index 7f0d8577eb..02731ec684 100644
--- a/bytecomp/translobj.ml
+++ b/bytecomp/translobj.ml
@@ -162,3 +162,14 @@ let oo_wrap env req f x =
wrapping := false;
top_env := Env.empty;
raise exn
+
+let reset () =
+ Hashtbl.clear consts;
+ cache_required := false;
+ method_cache := lambda_unit;
+ method_count := 0;
+ method_table := [];
+ wrapping := false;
+ top_env := Env.empty;
+ classes := [];
+ method_ids := IdentSet.empty
diff --git a/bytecomp/translobj.mli b/bytecomp/translobj.mli
index 55c1634332..a44ac683ff 100644
--- a/bytecomp/translobj.mli
+++ b/bytecomp/translobj.mli
@@ -26,3 +26,5 @@ val method_ids: IdentSet.t ref (* reset when starting a new wrapper *)
val oo_wrap: Env.t -> bool -> ('a -> lambda) -> 'a -> lambda
val oo_add_class: Ident.t -> Env.t * bool
+
+val reset: unit -> unit
diff --git a/byterun/.depend b/byterun/.depend
index a68ab0904e..2f1780db9e 100644
--- a/byterun/.depend
+++ b/byterun/.depend
@@ -1,419 +1,422 @@
alloc.o: alloc.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h major_gc.h freelist.h memory.h gc.h \
- minor_gc.h stacks.h
+ ../config/s.h mlvalues.h custom.h major_gc.h freelist.h memory.h gc.h \
+ minor_gc.h stacks.h
array.o: array.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h
+ ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h
backtrace.o: backtrace.c config.h ../config/m.h ../config/s.h \
- compatibility.h mlvalues.h misc.h alloc.h io.h instruct.h intext.h \
- exec.h fix_code.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
- startup.h stacks.h sys.h backtrace.h
+ compatibility.h mlvalues.h misc.h alloc.h io.h instruct.h intext.h \
+ exec.h fix_code.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ startup.h stacks.h sys.h backtrace.h
callback.o: callback.c callback.h compatibility.h mlvalues.h config.h \
- ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h interp.h instruct.h fix_code.h stacks.h
+ ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h interp.h instruct.h fix_code.h stacks.h
compact.o: compact.c config.h ../config/m.h ../config/s.h compatibility.h \
- finalise.h roots.h misc.h memory.h gc.h mlvalues.h major_gc.h freelist.h \
- minor_gc.h gc_ctrl.h weak.h
+ finalise.h roots.h misc.h memory.h gc.h mlvalues.h major_gc.h \
+ freelist.h minor_gc.h gc_ctrl.h weak.h
compare.o: compare.c custom.h compatibility.h mlvalues.h config.h \
- ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h
+ ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h
custom.o: custom.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h
+ ../config/s.h mlvalues.h custom.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h
debugger.o: debugger.c alloc.h compatibility.h misc.h config.h \
- ../config/m.h ../config/s.h mlvalues.h debugger.h fail.h fix_code.h \
- instruct.h intext.h io.h stacks.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h sys.h
+ ../config/m.h ../config/s.h mlvalues.h debugger.h fail.h fix_code.h \
+ instruct.h intext.h io.h stacks.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h sys.h
dynlink.o: dynlink.c config.h ../config/m.h ../config/s.h compatibility.h \
- alloc.h misc.h mlvalues.h dynlink.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h osdeps.h prims.h
+ alloc.h misc.h mlvalues.h dynlink.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h osdeps.h prims.h
extern.o: extern.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h fail.h gc.h intext.h io.h md5.h \
- memory.h major_gc.h freelist.h minor_gc.h reverse.h
+ ../config/s.h mlvalues.h custom.h fail.h gc.h intext.h io.h md5.h \
+ memory.h major_gc.h freelist.h minor_gc.h reverse.h
fail.o: fail.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h io.h gc.h memory.h major_gc.h freelist.h \
- minor_gc.h printexc.h signals.h stacks.h
+ ../config/s.h mlvalues.h fail.h io.h gc.h memory.h major_gc.h \
+ freelist.h minor_gc.h printexc.h signals.h stacks.h
finalise.o: finalise.c callback.h compatibility.h mlvalues.h config.h \
- ../config/m.h ../config/s.h misc.h fail.h roots.h memory.h gc.h \
- major_gc.h freelist.h minor_gc.h signals.h
+ ../config/m.h ../config/s.h misc.h fail.h roots.h memory.h gc.h \
+ major_gc.h freelist.h minor_gc.h signals.h
fix_code.o: fix_code.c config.h ../config/m.h ../config/s.h \
- compatibility.h debugger.h misc.h mlvalues.h fix_code.h instruct.h \
- intext.h io.h md5.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
- reverse.h
+ compatibility.h debugger.h misc.h mlvalues.h fix_code.h instruct.h \
+ intext.h io.h md5.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ reverse.h
floats.o: floats.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h reverse.h stacks.h
+ ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h reverse.h stacks.h
freelist.o: freelist.c config.h ../config/m.h ../config/s.h \
- compatibility.h freelist.h misc.h mlvalues.h gc.h gc_ctrl.h memory.h \
- major_gc.h minor_gc.h
+ compatibility.h freelist.h misc.h mlvalues.h gc.h gc_ctrl.h memory.h \
+ major_gc.h minor_gc.h
gc_ctrl.o: gc_ctrl.c alloc.h compatibility.h misc.h config.h \
- ../config/m.h ../config/s.h mlvalues.h compact.h custom.h finalise.h \
- roots.h memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h \
- stacks.h
+ ../config/m.h ../config/s.h mlvalues.h compact.h custom.h finalise.h \
+ roots.h memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h \
+ stacks.h
globroots.o: globroots.c memory.h compatibility.h config.h ../config/m.h \
- ../config/s.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
- roots.h globroots.h
+ ../config/s.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
+ roots.h globroots.h
hash.o: hash.c mlvalues.h compatibility.h config.h ../config/m.h \
- ../config/s.h misc.h custom.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h hash.h int64_native.h
+ ../config/s.h misc.h custom.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h hash.h int64_native.h
instrtrace.o: instrtrace.c
intern.o: intern.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h callback.h custom.h fail.h gc.h intext.h io.h \
- md5.h memory.h major_gc.h freelist.h minor_gc.h reverse.h
+ ../config/s.h mlvalues.h callback.h custom.h fail.h gc.h intext.h io.h \
+ md5.h memory.h major_gc.h freelist.h minor_gc.h reverse.h
interp.o: interp.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h backtrace.h callback.h debugger.h fail.h \
- fix_code.h instrtrace.h instruct.h interp.h major_gc.h freelist.h \
- memory.h gc.h minor_gc.h prims.h signals.h stacks.h jumptbl.h
+ ../config/s.h mlvalues.h backtrace.h callback.h debugger.h fail.h \
+ fix_code.h instrtrace.h instruct.h interp.h major_gc.h freelist.h \
+ memory.h gc.h minor_gc.h prims.h signals.h stacks.h jumptbl.h
ints.o: ints.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h fail.h intext.h io.h memory.h gc.h \
- major_gc.h freelist.h minor_gc.h int64_native.h
+ ../config/s.h mlvalues.h custom.h fail.h intext.h io.h memory.h gc.h \
+ major_gc.h freelist.h minor_gc.h int64_native.h
io.o: io.c config.h ../config/m.h ../config/s.h compatibility.h alloc.h \
- misc.h mlvalues.h custom.h fail.h io.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h signals.h sys.h
+ misc.h mlvalues.h custom.h fail.h io.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h signals.h sys.h
lexing.o: lexing.c fail.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h
+ ../config/s.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h
main.o: main.c misc.h compatibility.h config.h ../config/m.h \
- ../config/s.h mlvalues.h sys.h
+ ../config/s.h mlvalues.h sys.h
major_gc.o: major_gc.c compact.h config.h ../config/m.h ../config/s.h \
- compatibility.h misc.h custom.h mlvalues.h fail.h finalise.h roots.h \
- memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h weak.h
+ compatibility.h misc.h custom.h mlvalues.h fail.h finalise.h roots.h \
+ memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h weak.h
md5.o: md5.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h md5.h io.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h reverse.h
+ ../config/s.h mlvalues.h fail.h md5.h io.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h reverse.h
memory.o: memory.c fail.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h freelist.h gc.h gc_ctrl.h major_gc.h memory.h \
- minor_gc.h signals.h
+ ../config/s.h mlvalues.h freelist.h gc.h gc_ctrl.h major_gc.h memory.h \
+ minor_gc.h signals.h
meta.o: meta.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h fix_code.h interp.h intext.h io.h \
- major_gc.h freelist.h memory.h gc.h minor_gc.h prims.h stacks.h
+ ../config/s.h mlvalues.h fail.h fix_code.h interp.h intext.h io.h \
+ major_gc.h freelist.h memory.h gc.h minor_gc.h prims.h stacks.h
minor_gc.o: minor_gc.c config.h ../config/m.h ../config/s.h \
- compatibility.h fail.h misc.h mlvalues.h finalise.h roots.h memory.h \
- gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h signals.h weak.h
+ compatibility.h fail.h misc.h mlvalues.h finalise.h roots.h memory.h \
+ gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h signals.h weak.h
misc.o: misc.c config.h ../config/m.h ../config/s.h compatibility.h \
- misc.h memory.h gc.h mlvalues.h major_gc.h freelist.h minor_gc.h
+ misc.h memory.h gc.h mlvalues.h major_gc.h freelist.h minor_gc.h
obj.o: obj.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h gc.h interp.h major_gc.h freelist.h \
- memory.h minor_gc.h prims.h
+ ../config/s.h mlvalues.h fail.h gc.h interp.h major_gc.h freelist.h \
+ memory.h minor_gc.h prims.h
parsing.o: parsing.c config.h ../config/m.h ../config/s.h compatibility.h \
- mlvalues.h misc.h memory.h gc.h major_gc.h freelist.h minor_gc.h alloc.h
+ mlvalues.h misc.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ alloc.h
prims.o: prims.c mlvalues.h compatibility.h config.h ../config/m.h \
- ../config/s.h misc.h prims.h
+ ../config/s.h misc.h prims.h
printexc.o: printexc.c backtrace.h mlvalues.h compatibility.h config.h \
- ../config/m.h ../config/s.h misc.h callback.h debugger.h fail.h \
- printexc.h
+ ../config/m.h ../config/s.h misc.h callback.h debugger.h fail.h \
+ printexc.h
roots.o: roots.c finalise.h roots.h misc.h compatibility.h config.h \
- ../config/m.h ../config/s.h memory.h gc.h mlvalues.h major_gc.h \
- freelist.h minor_gc.h globroots.h stacks.h
+ ../config/m.h ../config/s.h memory.h gc.h mlvalues.h major_gc.h \
+ freelist.h minor_gc.h globroots.h stacks.h
signals.o: signals.c alloc.h compatibility.h misc.h config.h \
- ../config/m.h ../config/s.h mlvalues.h callback.h fail.h memory.h gc.h \
- major_gc.h freelist.h minor_gc.h roots.h signals.h signals_machdep.h \
- sys.h
+ ../config/m.h ../config/s.h mlvalues.h callback.h fail.h memory.h gc.h \
+ major_gc.h freelist.h minor_gc.h roots.h signals.h signals_machdep.h \
+ sys.h
signals_byt.o: signals_byt.c config.h ../config/m.h ../config/s.h \
- compatibility.h memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h \
- minor_gc.h osdeps.h signals.h signals_machdep.h
+ compatibility.h memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h \
+ minor_gc.h osdeps.h signals.h signals_machdep.h
stacks.o: stacks.c config.h ../config/m.h ../config/s.h compatibility.h \
- fail.h misc.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h
+ fail.h misc.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h
startup.o: startup.c config.h ../config/m.h ../config/s.h compatibility.h \
- alloc.h misc.h mlvalues.h backtrace.h callback.h custom.h debugger.h \
- dynlink.h exec.h fail.h fix_code.h freelist.h gc_ctrl.h instrtrace.h \
- interp.h intext.h io.h memory.h gc.h major_gc.h minor_gc.h osdeps.h \
- prims.h printexc.h reverse.h signals.h stacks.h sys.h startup.h \
- version.h
+ alloc.h misc.h mlvalues.h backtrace.h callback.h custom.h debugger.h \
+ dynlink.h exec.h fail.h fix_code.h freelist.h gc_ctrl.h instrtrace.h \
+ interp.h intext.h io.h memory.h gc.h major_gc.h minor_gc.h osdeps.h \
+ prims.h printexc.h reverse.h signals.h stacks.h sys.h startup.h \
+ version.h
str.o: str.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h int64_native.h
+ ../config/s.h mlvalues.h fail.h int64_native.h
sys.o: sys.c config.h ../config/m.h ../config/s.h compatibility.h alloc.h \
- misc.h mlvalues.h debugger.h fail.h instruct.h osdeps.h signals.h \
- stacks.h memory.h gc.h major_gc.h freelist.h minor_gc.h sys.h
+ misc.h mlvalues.h debugger.h fail.h instruct.h osdeps.h signals.h \
+ stacks.h memory.h gc.h major_gc.h freelist.h minor_gc.h sys.h
terminfo.o: terminfo.c config.h ../config/m.h ../config/s.h \
- compatibility.h alloc.h misc.h mlvalues.h fail.h io.h
+ compatibility.h alloc.h misc.h mlvalues.h fail.h io.h
unix.o: unix.c config.h ../config/m.h ../config/s.h compatibility.h \
- memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
- osdeps.h
+ memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
+ osdeps.h
weak.o: weak.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h major_gc.h freelist.h memory.h gc.h \
- minor_gc.h
+ ../config/s.h mlvalues.h fail.h major_gc.h freelist.h memory.h gc.h \
+ minor_gc.h
win32.o: win32.c fail.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
- osdeps.h signals.h sys.h
+ ../config/s.h mlvalues.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ osdeps.h signals.h sys.h
alloc.d.o: alloc.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h major_gc.h freelist.h memory.h gc.h \
- minor_gc.h stacks.h
+ ../config/s.h mlvalues.h custom.h major_gc.h freelist.h memory.h gc.h \
+ minor_gc.h stacks.h
array.d.o: array.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h
+ ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h
backtrace.d.o: backtrace.c config.h ../config/m.h ../config/s.h \
- compatibility.h mlvalues.h misc.h alloc.h io.h instruct.h intext.h \
- exec.h fix_code.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
- startup.h stacks.h sys.h backtrace.h
+ compatibility.h mlvalues.h misc.h alloc.h io.h instruct.h intext.h \
+ exec.h fix_code.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ startup.h stacks.h sys.h backtrace.h
callback.d.o: callback.c callback.h compatibility.h mlvalues.h config.h \
- ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h interp.h instruct.h fix_code.h stacks.h
+ ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h interp.h instruct.h fix_code.h stacks.h
compact.d.o: compact.c config.h ../config/m.h ../config/s.h compatibility.h \
- finalise.h roots.h misc.h memory.h gc.h mlvalues.h major_gc.h freelist.h \
- minor_gc.h gc_ctrl.h weak.h
+ finalise.h roots.h misc.h memory.h gc.h mlvalues.h major_gc.h \
+ freelist.h minor_gc.h gc_ctrl.h weak.h
compare.d.o: compare.c custom.h compatibility.h mlvalues.h config.h \
- ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h
+ ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h
custom.d.o: custom.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h
+ ../config/s.h mlvalues.h custom.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h
debugger.d.o: debugger.c alloc.h compatibility.h misc.h config.h \
- ../config/m.h ../config/s.h mlvalues.h debugger.h fail.h fix_code.h \
- instruct.h intext.h io.h stacks.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h sys.h
+ ../config/m.h ../config/s.h mlvalues.h debugger.h fail.h fix_code.h \
+ instruct.h intext.h io.h stacks.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h sys.h
dynlink.d.o: dynlink.c config.h ../config/m.h ../config/s.h compatibility.h \
- alloc.h misc.h mlvalues.h dynlink.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h osdeps.h prims.h
+ alloc.h misc.h mlvalues.h dynlink.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h osdeps.h prims.h
extern.d.o: extern.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h fail.h gc.h intext.h io.h md5.h \
- memory.h major_gc.h freelist.h minor_gc.h reverse.h
+ ../config/s.h mlvalues.h custom.h fail.h gc.h intext.h io.h md5.h \
+ memory.h major_gc.h freelist.h minor_gc.h reverse.h
fail.d.o: fail.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h io.h gc.h memory.h major_gc.h freelist.h \
- minor_gc.h printexc.h signals.h stacks.h
+ ../config/s.h mlvalues.h fail.h io.h gc.h memory.h major_gc.h \
+ freelist.h minor_gc.h printexc.h signals.h stacks.h
finalise.d.o: finalise.c callback.h compatibility.h mlvalues.h config.h \
- ../config/m.h ../config/s.h misc.h fail.h roots.h memory.h gc.h \
- major_gc.h freelist.h minor_gc.h signals.h
+ ../config/m.h ../config/s.h misc.h fail.h roots.h memory.h gc.h \
+ major_gc.h freelist.h minor_gc.h signals.h
fix_code.d.o: fix_code.c config.h ../config/m.h ../config/s.h \
- compatibility.h debugger.h misc.h mlvalues.h fix_code.h instruct.h \
- intext.h io.h md5.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
- reverse.h
+ compatibility.h debugger.h misc.h mlvalues.h fix_code.h instruct.h \
+ intext.h io.h md5.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ reverse.h
floats.d.o: floats.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h reverse.h stacks.h
+ ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h reverse.h stacks.h
freelist.d.o: freelist.c config.h ../config/m.h ../config/s.h \
- compatibility.h freelist.h misc.h mlvalues.h gc.h gc_ctrl.h memory.h \
- major_gc.h minor_gc.h
+ compatibility.h freelist.h misc.h mlvalues.h gc.h gc_ctrl.h memory.h \
+ major_gc.h minor_gc.h
gc_ctrl.d.o: gc_ctrl.c alloc.h compatibility.h misc.h config.h \
- ../config/m.h ../config/s.h mlvalues.h compact.h custom.h finalise.h \
- roots.h memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h \
- stacks.h
+ ../config/m.h ../config/s.h mlvalues.h compact.h custom.h finalise.h \
+ roots.h memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h \
+ stacks.h
globroots.d.o: globroots.c memory.h compatibility.h config.h ../config/m.h \
- ../config/s.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
- roots.h globroots.h
+ ../config/s.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
+ roots.h globroots.h
hash.d.o: hash.c mlvalues.h compatibility.h config.h ../config/m.h \
- ../config/s.h misc.h custom.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h hash.h int64_native.h
+ ../config/s.h misc.h custom.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h hash.h int64_native.h
instrtrace.d.o: instrtrace.c instruct.h misc.h compatibility.h config.h \
- ../config/m.h ../config/s.h mlvalues.h opnames.h prims.h stacks.h \
- memory.h gc.h major_gc.h freelist.h minor_gc.h
+ ../config/m.h ../config/s.h mlvalues.h opnames.h prims.h stacks.h \
+ memory.h gc.h major_gc.h freelist.h minor_gc.h
intern.d.o: intern.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h callback.h custom.h fail.h gc.h intext.h io.h \
- md5.h memory.h major_gc.h freelist.h minor_gc.h reverse.h
+ ../config/s.h mlvalues.h callback.h custom.h fail.h gc.h intext.h io.h \
+ md5.h memory.h major_gc.h freelist.h minor_gc.h reverse.h
interp.d.o: interp.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h backtrace.h callback.h debugger.h fail.h \
- fix_code.h instrtrace.h instruct.h interp.h major_gc.h freelist.h \
- memory.h gc.h minor_gc.h prims.h signals.h stacks.h
+ ../config/s.h mlvalues.h backtrace.h callback.h debugger.h fail.h \
+ fix_code.h instrtrace.h instruct.h interp.h major_gc.h freelist.h \
+ memory.h gc.h minor_gc.h prims.h signals.h stacks.h
ints.d.o: ints.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h fail.h intext.h io.h memory.h gc.h \
- major_gc.h freelist.h minor_gc.h int64_native.h
+ ../config/s.h mlvalues.h custom.h fail.h intext.h io.h memory.h gc.h \
+ major_gc.h freelist.h minor_gc.h int64_native.h
io.d.o: io.c config.h ../config/m.h ../config/s.h compatibility.h alloc.h \
- misc.h mlvalues.h custom.h fail.h io.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h signals.h sys.h
+ misc.h mlvalues.h custom.h fail.h io.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h signals.h sys.h
lexing.d.o: lexing.c fail.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h
+ ../config/s.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h
main.d.o: main.c misc.h compatibility.h config.h ../config/m.h \
- ../config/s.h mlvalues.h sys.h
+ ../config/s.h mlvalues.h sys.h
major_gc.d.o: major_gc.c compact.h config.h ../config/m.h ../config/s.h \
- compatibility.h misc.h custom.h mlvalues.h fail.h finalise.h roots.h \
- memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h weak.h
+ compatibility.h misc.h custom.h mlvalues.h fail.h finalise.h roots.h \
+ memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h weak.h
md5.d.o: md5.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h md5.h io.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h reverse.h
+ ../config/s.h mlvalues.h fail.h md5.h io.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h reverse.h
memory.d.o: memory.c fail.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h freelist.h gc.h gc_ctrl.h major_gc.h memory.h \
- minor_gc.h signals.h
+ ../config/s.h mlvalues.h freelist.h gc.h gc_ctrl.h major_gc.h memory.h \
+ minor_gc.h signals.h
meta.d.o: meta.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h fix_code.h interp.h intext.h io.h \
- major_gc.h freelist.h memory.h gc.h minor_gc.h prims.h stacks.h
+ ../config/s.h mlvalues.h fail.h fix_code.h interp.h intext.h io.h \
+ major_gc.h freelist.h memory.h gc.h minor_gc.h prims.h stacks.h
minor_gc.d.o: minor_gc.c config.h ../config/m.h ../config/s.h \
- compatibility.h fail.h misc.h mlvalues.h finalise.h roots.h memory.h \
- gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h signals.h weak.h
+ compatibility.h fail.h misc.h mlvalues.h finalise.h roots.h memory.h \
+ gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h signals.h weak.h
misc.d.o: misc.c config.h ../config/m.h ../config/s.h compatibility.h \
- misc.h memory.h gc.h mlvalues.h major_gc.h freelist.h minor_gc.h
+ misc.h memory.h gc.h mlvalues.h major_gc.h freelist.h minor_gc.h
obj.d.o: obj.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h gc.h interp.h major_gc.h freelist.h \
- memory.h minor_gc.h prims.h
+ ../config/s.h mlvalues.h fail.h gc.h interp.h major_gc.h freelist.h \
+ memory.h minor_gc.h prims.h
parsing.d.o: parsing.c config.h ../config/m.h ../config/s.h compatibility.h \
- mlvalues.h misc.h memory.h gc.h major_gc.h freelist.h minor_gc.h alloc.h
+ mlvalues.h misc.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ alloc.h
prims.d.o: prims.c mlvalues.h compatibility.h config.h ../config/m.h \
- ../config/s.h misc.h prims.h
+ ../config/s.h misc.h prims.h
printexc.d.o: printexc.c backtrace.h mlvalues.h compatibility.h config.h \
- ../config/m.h ../config/s.h misc.h callback.h debugger.h fail.h \
- printexc.h
+ ../config/m.h ../config/s.h misc.h callback.h debugger.h fail.h \
+ printexc.h
roots.d.o: roots.c finalise.h roots.h misc.h compatibility.h config.h \
- ../config/m.h ../config/s.h memory.h gc.h mlvalues.h major_gc.h \
- freelist.h minor_gc.h globroots.h stacks.h
+ ../config/m.h ../config/s.h memory.h gc.h mlvalues.h major_gc.h \
+ freelist.h minor_gc.h globroots.h stacks.h
signals.d.o: signals.c alloc.h compatibility.h misc.h config.h \
- ../config/m.h ../config/s.h mlvalues.h callback.h fail.h memory.h gc.h \
- major_gc.h freelist.h minor_gc.h roots.h signals.h signals_machdep.h \
- sys.h
+ ../config/m.h ../config/s.h mlvalues.h callback.h fail.h memory.h gc.h \
+ major_gc.h freelist.h minor_gc.h roots.h signals.h signals_machdep.h \
+ sys.h
signals_byt.d.o: signals_byt.c config.h ../config/m.h ../config/s.h \
- compatibility.h memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h \
- minor_gc.h osdeps.h signals.h signals_machdep.h
+ compatibility.h memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h \
+ minor_gc.h osdeps.h signals.h signals_machdep.h
stacks.d.o: stacks.c config.h ../config/m.h ../config/s.h compatibility.h \
- fail.h misc.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h
+ fail.h misc.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h
startup.d.o: startup.c config.h ../config/m.h ../config/s.h compatibility.h \
- alloc.h misc.h mlvalues.h backtrace.h callback.h custom.h debugger.h \
- dynlink.h exec.h fail.h fix_code.h freelist.h gc_ctrl.h instrtrace.h \
- interp.h intext.h io.h memory.h gc.h major_gc.h minor_gc.h osdeps.h \
- prims.h printexc.h reverse.h signals.h stacks.h sys.h startup.h \
- version.h
+ alloc.h misc.h mlvalues.h backtrace.h callback.h custom.h debugger.h \
+ dynlink.h exec.h fail.h fix_code.h freelist.h gc_ctrl.h instrtrace.h \
+ interp.h intext.h io.h memory.h gc.h major_gc.h minor_gc.h osdeps.h \
+ prims.h printexc.h reverse.h signals.h stacks.h sys.h startup.h \
+ version.h
str.d.o: str.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h int64_native.h
+ ../config/s.h mlvalues.h fail.h int64_native.h
sys.d.o: sys.c config.h ../config/m.h ../config/s.h compatibility.h alloc.h \
- misc.h mlvalues.h debugger.h fail.h instruct.h osdeps.h signals.h \
- stacks.h memory.h gc.h major_gc.h freelist.h minor_gc.h sys.h
+ misc.h mlvalues.h debugger.h fail.h instruct.h osdeps.h signals.h \
+ stacks.h memory.h gc.h major_gc.h freelist.h minor_gc.h sys.h
terminfo.d.o: terminfo.c config.h ../config/m.h ../config/s.h \
- compatibility.h alloc.h misc.h mlvalues.h fail.h io.h
+ compatibility.h alloc.h misc.h mlvalues.h fail.h io.h
unix.d.o: unix.c config.h ../config/m.h ../config/s.h compatibility.h \
- memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
- osdeps.h
+ memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
+ osdeps.h
weak.d.o: weak.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h major_gc.h freelist.h memory.h gc.h \
- minor_gc.h
+ ../config/s.h mlvalues.h fail.h major_gc.h freelist.h memory.h gc.h \
+ minor_gc.h
win32.d.o: win32.c fail.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
- osdeps.h signals.h sys.h
+ ../config/s.h mlvalues.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ osdeps.h signals.h sys.h
alloc.pic.o: alloc.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h major_gc.h freelist.h memory.h gc.h \
- minor_gc.h stacks.h
+ ../config/s.h mlvalues.h custom.h major_gc.h freelist.h memory.h gc.h \
+ minor_gc.h stacks.h
array.pic.o: array.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h
+ ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h
backtrace.pic.o: backtrace.c config.h ../config/m.h ../config/s.h \
- compatibility.h mlvalues.h misc.h alloc.h io.h instruct.h intext.h \
- exec.h fix_code.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
- startup.h stacks.h sys.h backtrace.h
+ compatibility.h mlvalues.h misc.h alloc.h io.h instruct.h intext.h \
+ exec.h fix_code.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ startup.h stacks.h sys.h backtrace.h
callback.pic.o: callback.c callback.h compatibility.h mlvalues.h config.h \
- ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h interp.h instruct.h fix_code.h stacks.h
+ ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h interp.h instruct.h fix_code.h stacks.h
compact.pic.o: compact.c config.h ../config/m.h ../config/s.h compatibility.h \
- finalise.h roots.h misc.h memory.h gc.h mlvalues.h major_gc.h freelist.h \
- minor_gc.h gc_ctrl.h weak.h
+ finalise.h roots.h misc.h memory.h gc.h mlvalues.h major_gc.h \
+ freelist.h minor_gc.h gc_ctrl.h weak.h
compare.pic.o: compare.c custom.h compatibility.h mlvalues.h config.h \
- ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h
+ ../config/m.h ../config/s.h misc.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h
custom.pic.o: custom.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h
+ ../config/s.h mlvalues.h custom.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h
debugger.pic.o: debugger.c alloc.h compatibility.h misc.h config.h \
- ../config/m.h ../config/s.h mlvalues.h debugger.h fail.h fix_code.h \
- instruct.h intext.h io.h stacks.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h sys.h
+ ../config/m.h ../config/s.h mlvalues.h debugger.h fail.h fix_code.h \
+ instruct.h intext.h io.h stacks.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h sys.h
dynlink.pic.o: dynlink.c config.h ../config/m.h ../config/s.h compatibility.h \
- alloc.h misc.h mlvalues.h dynlink.h fail.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h osdeps.h prims.h
+ alloc.h misc.h mlvalues.h dynlink.h fail.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h osdeps.h prims.h
extern.pic.o: extern.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h fail.h gc.h intext.h io.h md5.h \
- memory.h major_gc.h freelist.h minor_gc.h reverse.h
+ ../config/s.h mlvalues.h custom.h fail.h gc.h intext.h io.h md5.h \
+ memory.h major_gc.h freelist.h minor_gc.h reverse.h
fail.pic.o: fail.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h io.h gc.h memory.h major_gc.h freelist.h \
- minor_gc.h printexc.h signals.h stacks.h
+ ../config/s.h mlvalues.h fail.h io.h gc.h memory.h major_gc.h \
+ freelist.h minor_gc.h printexc.h signals.h stacks.h
finalise.pic.o: finalise.c callback.h compatibility.h mlvalues.h config.h \
- ../config/m.h ../config/s.h misc.h fail.h roots.h memory.h gc.h \
- major_gc.h freelist.h minor_gc.h signals.h
+ ../config/m.h ../config/s.h misc.h fail.h roots.h memory.h gc.h \
+ major_gc.h freelist.h minor_gc.h signals.h
fix_code.pic.o: fix_code.c config.h ../config/m.h ../config/s.h \
- compatibility.h debugger.h misc.h mlvalues.h fix_code.h instruct.h \
- intext.h io.h md5.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
- reverse.h
+ compatibility.h debugger.h misc.h mlvalues.h fix_code.h instruct.h \
+ intext.h io.h md5.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ reverse.h
floats.pic.o: floats.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h reverse.h stacks.h
+ ../config/s.h mlvalues.h fail.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h reverse.h stacks.h
freelist.pic.o: freelist.c config.h ../config/m.h ../config/s.h \
- compatibility.h freelist.h misc.h mlvalues.h gc.h gc_ctrl.h memory.h \
- major_gc.h minor_gc.h
+ compatibility.h freelist.h misc.h mlvalues.h gc.h gc_ctrl.h memory.h \
+ major_gc.h minor_gc.h
gc_ctrl.pic.o: gc_ctrl.c alloc.h compatibility.h misc.h config.h \
- ../config/m.h ../config/s.h mlvalues.h compact.h custom.h finalise.h \
- roots.h memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h \
- stacks.h
+ ../config/m.h ../config/s.h mlvalues.h compact.h custom.h finalise.h \
+ roots.h memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h \
+ stacks.h
globroots.pic.o: globroots.c memory.h compatibility.h config.h ../config/m.h \
- ../config/s.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
- roots.h globroots.h
+ ../config/s.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
+ roots.h globroots.h
hash.pic.o: hash.c mlvalues.h compatibility.h config.h ../config/m.h \
- ../config/s.h misc.h custom.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h hash.h int64_native.h
+ ../config/s.h misc.h custom.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h hash.h int64_native.h
instrtrace.pic.o: instrtrace.c
intern.pic.o: intern.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h callback.h custom.h fail.h gc.h intext.h io.h \
- md5.h memory.h major_gc.h freelist.h minor_gc.h reverse.h
+ ../config/s.h mlvalues.h callback.h custom.h fail.h gc.h intext.h io.h \
+ md5.h memory.h major_gc.h freelist.h minor_gc.h reverse.h
interp.pic.o: interp.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h backtrace.h callback.h debugger.h fail.h \
- fix_code.h instrtrace.h instruct.h interp.h major_gc.h freelist.h \
- memory.h gc.h minor_gc.h prims.h signals.h stacks.h jumptbl.h
+ ../config/s.h mlvalues.h backtrace.h callback.h debugger.h fail.h \
+ fix_code.h instrtrace.h instruct.h interp.h major_gc.h freelist.h \
+ memory.h gc.h minor_gc.h prims.h signals.h stacks.h jumptbl.h
ints.pic.o: ints.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h custom.h fail.h intext.h io.h memory.h gc.h \
- major_gc.h freelist.h minor_gc.h int64_native.h
+ ../config/s.h mlvalues.h custom.h fail.h intext.h io.h memory.h gc.h \
+ major_gc.h freelist.h minor_gc.h int64_native.h
io.pic.o: io.c config.h ../config/m.h ../config/s.h compatibility.h alloc.h \
- misc.h mlvalues.h custom.h fail.h io.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h signals.h sys.h
+ misc.h mlvalues.h custom.h fail.h io.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h signals.h sys.h
lexing.pic.o: lexing.c fail.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h
+ ../config/s.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h
main.pic.o: main.c misc.h compatibility.h config.h ../config/m.h \
- ../config/s.h mlvalues.h sys.h
+ ../config/s.h mlvalues.h sys.h
major_gc.pic.o: major_gc.c compact.h config.h ../config/m.h ../config/s.h \
- compatibility.h misc.h custom.h mlvalues.h fail.h finalise.h roots.h \
- memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h weak.h
+ compatibility.h misc.h custom.h mlvalues.h fail.h finalise.h roots.h \
+ memory.h gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h weak.h
md5.pic.o: md5.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h md5.h io.h memory.h gc.h major_gc.h \
- freelist.h minor_gc.h reverse.h
+ ../config/s.h mlvalues.h fail.h md5.h io.h memory.h gc.h major_gc.h \
+ freelist.h minor_gc.h reverse.h
memory.pic.o: memory.c fail.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h freelist.h gc.h gc_ctrl.h major_gc.h memory.h \
- minor_gc.h signals.h
+ ../config/s.h mlvalues.h freelist.h gc.h gc_ctrl.h major_gc.h memory.h \
+ minor_gc.h signals.h
meta.pic.o: meta.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h fix_code.h interp.h intext.h io.h \
- major_gc.h freelist.h memory.h gc.h minor_gc.h prims.h stacks.h
+ ../config/s.h mlvalues.h fail.h fix_code.h interp.h intext.h io.h \
+ major_gc.h freelist.h memory.h gc.h minor_gc.h prims.h stacks.h
minor_gc.pic.o: minor_gc.c config.h ../config/m.h ../config/s.h \
- compatibility.h fail.h misc.h mlvalues.h finalise.h roots.h memory.h \
- gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h signals.h weak.h
+ compatibility.h fail.h misc.h mlvalues.h finalise.h roots.h memory.h \
+ gc.h major_gc.h freelist.h minor_gc.h gc_ctrl.h signals.h weak.h
misc.pic.o: misc.c config.h ../config/m.h ../config/s.h compatibility.h \
- misc.h memory.h gc.h mlvalues.h major_gc.h freelist.h minor_gc.h
+ misc.h memory.h gc.h mlvalues.h major_gc.h freelist.h minor_gc.h
obj.pic.o: obj.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h gc.h interp.h major_gc.h freelist.h \
- memory.h minor_gc.h prims.h
+ ../config/s.h mlvalues.h fail.h gc.h interp.h major_gc.h freelist.h \
+ memory.h minor_gc.h prims.h
parsing.pic.o: parsing.c config.h ../config/m.h ../config/s.h compatibility.h \
- mlvalues.h misc.h memory.h gc.h major_gc.h freelist.h minor_gc.h alloc.h
+ mlvalues.h misc.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ alloc.h
prims.pic.o: prims.c mlvalues.h compatibility.h config.h ../config/m.h \
- ../config/s.h misc.h prims.h
+ ../config/s.h misc.h prims.h
printexc.pic.o: printexc.c backtrace.h mlvalues.h compatibility.h config.h \
- ../config/m.h ../config/s.h misc.h callback.h debugger.h fail.h \
- printexc.h
+ ../config/m.h ../config/s.h misc.h callback.h debugger.h fail.h \
+ printexc.h
roots.pic.o: roots.c finalise.h roots.h misc.h compatibility.h config.h \
- ../config/m.h ../config/s.h memory.h gc.h mlvalues.h major_gc.h \
- freelist.h minor_gc.h globroots.h stacks.h
+ ../config/m.h ../config/s.h memory.h gc.h mlvalues.h major_gc.h \
+ freelist.h minor_gc.h globroots.h stacks.h
signals.pic.o: signals.c alloc.h compatibility.h misc.h config.h \
- ../config/m.h ../config/s.h mlvalues.h callback.h fail.h memory.h gc.h \
- major_gc.h freelist.h minor_gc.h roots.h signals.h signals_machdep.h \
- sys.h
+ ../config/m.h ../config/s.h mlvalues.h callback.h fail.h memory.h gc.h \
+ major_gc.h freelist.h minor_gc.h roots.h signals.h signals_machdep.h \
+ sys.h
signals_byt.pic.o: signals_byt.c config.h ../config/m.h ../config/s.h \
- compatibility.h memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h \
- minor_gc.h osdeps.h signals.h signals_machdep.h
+ compatibility.h memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h \
+ minor_gc.h osdeps.h signals.h signals_machdep.h
stacks.pic.o: stacks.c config.h ../config/m.h ../config/s.h compatibility.h \
- fail.h misc.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
- minor_gc.h
+ fail.h misc.h mlvalues.h stacks.h memory.h gc.h major_gc.h freelist.h \
+ minor_gc.h
startup.pic.o: startup.c config.h ../config/m.h ../config/s.h compatibility.h \
- alloc.h misc.h mlvalues.h backtrace.h callback.h custom.h debugger.h \
- dynlink.h exec.h fail.h fix_code.h freelist.h gc_ctrl.h instrtrace.h \
- interp.h intext.h io.h memory.h gc.h major_gc.h minor_gc.h osdeps.h \
- prims.h printexc.h reverse.h signals.h stacks.h sys.h startup.h \
- version.h
+ alloc.h misc.h mlvalues.h backtrace.h callback.h custom.h debugger.h \
+ dynlink.h exec.h fail.h fix_code.h freelist.h gc_ctrl.h instrtrace.h \
+ interp.h intext.h io.h memory.h gc.h major_gc.h minor_gc.h osdeps.h \
+ prims.h printexc.h reverse.h signals.h stacks.h sys.h startup.h \
+ version.h
str.pic.o: str.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h int64_native.h
+ ../config/s.h mlvalues.h fail.h int64_native.h
sys.pic.o: sys.c config.h ../config/m.h ../config/s.h compatibility.h alloc.h \
- misc.h mlvalues.h debugger.h fail.h instruct.h osdeps.h signals.h \
- stacks.h memory.h gc.h major_gc.h freelist.h minor_gc.h sys.h
+ misc.h mlvalues.h debugger.h fail.h instruct.h osdeps.h signals.h \
+ stacks.h memory.h gc.h major_gc.h freelist.h minor_gc.h sys.h
terminfo.pic.o: terminfo.c config.h ../config/m.h ../config/s.h \
- compatibility.h alloc.h misc.h mlvalues.h fail.h io.h
+ compatibility.h alloc.h misc.h mlvalues.h fail.h io.h
unix.pic.o: unix.c config.h ../config/m.h ../config/s.h compatibility.h \
- memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
- osdeps.h
+ memory.h gc.h mlvalues.h misc.h major_gc.h freelist.h minor_gc.h \
+ osdeps.h
weak.pic.o: weak.c alloc.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h fail.h major_gc.h freelist.h memory.h gc.h \
- minor_gc.h
+ ../config/s.h mlvalues.h fail.h major_gc.h freelist.h memory.h gc.h \
+ minor_gc.h
win32.pic.o: win32.c fail.h compatibility.h misc.h config.h ../config/m.h \
- ../config/s.h mlvalues.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
- osdeps.h signals.h sys.h
+ ../config/s.h mlvalues.h memory.h gc.h major_gc.h freelist.h minor_gc.h \
+ osdeps.h signals.h sys.h
diff --git a/byterun/Makefile.common b/byterun/Makefile.common
index d2db39fe40..b6bff21948 100755
--- a/byterun/Makefile.common
+++ b/byterun/Makefile.common
@@ -32,7 +32,8 @@ PRIMS=\
PUBLIC_INCLUDES=\
alloc.h callback.h config.h custom.h fail.h hash.h intext.h \
- memory.h misc.h mlvalues.h printexc.h signals.h compatibility.h
+ memory.h misc.h mlvalues.h printexc.h signals.h compatibility.h \
+ version.h
all:: ocamlrun$(EXE) ld.conf libcamlrun.$(A) all-$(RUNTIMED)
@@ -117,8 +118,8 @@ jumptbl.h : instruct.h
sed -n -e '/^ /s/ \([A-Z]\)/ \&\&lbl_\1/gp' \
-e '/^}/q' instruct.h > jumptbl.h
-version.h : ../VERSION
- echo "#define OCAML_VERSION \"`sed -e 1q ../VERSION`\"" > version.h
+version.h : ../VERSION ../tools/make-version-header.sh
+ ../tools/make-version-header.sh ../VERSION > version.h
clean ::
rm -f ocamlrun$(EXE) ocamlrund$(EXE) *.$(O) *.$(A) *.$(SO)
diff --git a/byterun/alloc.c b/byterun/alloc.c
index a1fd2f03ed..1fc33b55a2 100644
--- a/byterun/alloc.c
+++ b/byterun/alloc.c
@@ -39,11 +39,13 @@ CAMLexport value caml_alloc (mlsize_t wosize, tag_t tag)
}else if (wosize <= Max_young_wosize){
Alloc_small (result, wosize, tag);
if (tag < No_scan_tag){
- for (i = 0; i < wosize; i++) Field (result, i) = 0;
+ for (i = 0; i < wosize; i++) Field (result, i) = Val_unit;
}
}else{
result = caml_alloc_shr (wosize, tag);
- if (tag < No_scan_tag) memset (Bp_val (result), 0, Bsize_wsize (wosize));
+ if (tag < No_scan_tag){
+ for (i = 0; i < wosize; i++) Field (result, i) = Val_unit;
+ }
result = caml_check_urgent_gc (result);
}
return result;
diff --git a/byterun/array.c b/byterun/array.c
index 327f2b5647..ba6fd701bc 100644
--- a/byterun/array.c
+++ b/byterun/array.c
@@ -214,9 +214,13 @@ CAMLprim value caml_make_array(value init)
|| Tag_val(v) != Double_tag) {
CAMLreturn (init);
} else {
- Assert(size < Max_young_wosize);
wsize = size * Double_wosize;
- res = caml_alloc_small(wsize, Double_array_tag);
+ 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++) {
Store_double_field(res, i, Double_val(Field(init, i)));
}
diff --git a/byterun/backtrace.c b/byterun/backtrace.c
index d39e395290..9b8022a306 100644
--- a/byterun/backtrace.c
+++ b/byterun/backtrace.c
@@ -35,6 +35,7 @@
#include "stacks.h"
#include "sys.h"
#include "backtrace.h"
+#include "fail.h"
CAMLexport int caml_backtrace_active = 0;
CAMLexport int caml_backtrace_pos = 0;
@@ -102,6 +103,7 @@ void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise)
caml_backtrace_last_exn = exn;
}
if (caml_backtrace_buffer == NULL) {
+ Assert(caml_backtrace_pos == 0);
caml_backtrace_buffer = malloc(BACKTRACE_BUFFER_SIZE * sizeof(code_t));
if (caml_backtrace_buffer == NULL) return;
}
@@ -119,6 +121,17 @@ void caml_stash_backtrace(value exn, code_t pc, value * sp, int reraise)
}
}
+/* In order to prevent the GC from walking through the debug
+ information (which have no headers), we transform code pointers to
+ 31/63 bits ocaml integers by shifting them by 1 to the right. We do
+ not lose information as code pointers are aligned.
+
+ In particular, we do not need to use [caml_initialize] when setting
+ an array element with such a value.
+*/
+#define Val_Codet(p) Val_long((uintnat)p>>1)
+#define Codet_Val(v) ((code_t)(Long_val(v)<<1))
+
/* returns the next frame pointer (or NULL if none is available);
updates *sp to point to the following one, and *trapsp to the next
trap frame, which we will skip when we reach it */
@@ -165,7 +178,7 @@ CAMLprim value caml_get_current_callstack(value max_frames_value) {
}
}
- trace = caml_alloc(trace_size, Abstract_tag);
+ trace = caml_alloc(trace_size, 0);
/* then collect the trace */
{
@@ -176,36 +189,52 @@ CAMLprim value caml_get_current_callstack(value max_frames_value) {
for (trace_pos = 0; trace_pos < trace_size; trace_pos++) {
code_t p = caml_next_frame_pointer(&sp, &trapsp);
Assert(p != NULL);
- /* The assignment below is safe without [caml_initialize], even
- if the trace is large and allocated on the old heap, because
- we assign values that are outside the OCaml heap. */
- Assert(!(Is_block((value) p) && Is_in_heap((value) p)));
- Field(trace, trace_pos) = (value) p;
+ Field(trace, trace_pos) = Val_Codet(p);
}
}
CAMLreturn(trace);
}
-/* Read the debugging info contained in the current bytecode executable.
- Return an OCaml array of OCaml lists of debug_event records in "events",
- or Val_false on failure. */
+/* Read the debugging info contained in the current bytecode executable. */
#ifndef O_BINARY
#define O_BINARY 0
#endif
+struct ev_info {
+ code_t ev_pc;
+ char * ev_filename;
+ int ev_lnum;
+ int ev_startchr;
+ int ev_endchr;
+};
+
+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 char *read_debug_info_error = "";
-static value read_debug_info(void)
+static uintnat n_events;
+static struct ev_info *events = NULL;
+static void read_debug_info(void)
{
CAMLparam0();
- CAMLlocal1(events);
+ CAMLlocal1(events_heap);
char * exec_name;
int fd;
struct exec_trailer trail;
struct channel * chan;
uint32 num_events, orig, i;
- value evl, l;
+ intnat j;
+ value evl, l, ev_start;
+
+ if(events != NULL)
+ CAMLreturn0;
if (caml_cds_file != NULL) {
exec_name = caml_cds_file;
@@ -215,17 +244,18 @@ static value read_debug_info(void)
fd = caml_attempt_open(&exec_name, &trail, 1);
if (fd < 0){
read_debug_info_error = "executable program file not found";
- CAMLreturn(Val_false);
+ CAMLreturn0;
}
caml_read_section_descriptors(fd, &trail);
if (caml_seek_optional_section(fd, &trail, "DBUG") == -1) {
close(fd);
read_debug_info_error = "program not linked with -g";
- CAMLreturn(Val_false);
+ CAMLreturn0;
}
chan = caml_open_descriptor_in(fd);
num_events = caml_getword(chan);
- events = caml_alloc(num_events, 0);
+ n_events = 0;
+ events_heap = caml_alloc(num_events, 0);
for (i = 0; i < num_events; i++) {
orig = caml_getword(chan);
evl = caml_input_val(chan);
@@ -234,36 +264,82 @@ static value read_debug_info(void)
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);
+ n_events++;
}
/* Record event list */
- Store_field(events, i, evl);
+ Store_field(events_heap, i, evl);
}
caml_close_channel(chan);
- CAMLreturn(events);
+
+ events = (struct ev_info*)malloc(n_events * sizeof(struct ev_info));
+ if(events == NULL) {
+ read_debug_info_error = "out of memory";
+ CAMLreturn0;
+ }
+
+ j = 0;
+ for (i = 0; i < num_events; i++) {
+ for (l = Field(events_heap, i); l != Val_int(0); l = Field(l, 1)) {
+ uintnat fnsz;
+ value ev = Field(l, 0);
+
+ events[j].ev_pc =
+ (code_t)((char*)caml_start_code + Long_val(Field(ev, EV_POS)));
+
+ ev_start = Field (Field (ev, EV_LOC), LOC_START);
+
+ fnsz = caml_string_length(Field (ev_start, POS_FNAME))+1;
+ events[j].ev_filename = (char*)malloc(fnsz);
+ if(events[j].ev_filename == NULL) {
+ for(j--; j >= 0; j--)
+ free(events[j].ev_filename);
+ free(events);
+ events = NULL;
+ read_debug_info_error = "out of memory";
+ CAMLreturn0;
+ }
+ 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++;
+ }
+ }
+
+ Assert(j == n_events);
+
+ qsort(events, n_events, sizeof(struct ev_info), cmp_ev_info);
+
+ CAMLreturn0;
}
-/* Search the event for the given PC. Return Val_false if not found. */
+/* Search the event index for the given PC. Return -1 if not found. */
-static value event_for_location(value events, code_t pc)
+static intnat event_for_location(code_t pc)
{
- mlsize_t i;
- value pos, l, ev, ev_pos, best_ev;
-
- best_ev = 0;
+ uintnat low = 0, high = n_events;
Assert(pc >= caml_start_code && pc < caml_start_code + caml_code_size);
- pos = Val_long((char *) pc - (char *) caml_start_code);
- for (i = 0; i < Wosize_val(events); i++) {
- for (l = Field(events, i); l != Val_int(0); l = Field(l, 1)) {
- ev = Field(l, 0);
- ev_pos = Field(ev, EV_POS);
- if (ev_pos == pos) return ev;
- /* ocamlc sometimes moves an event past a following PUSH instruction;
- allow mismatch by 1 instruction. */
- if (ev_pos == pos + 8) best_ev = ev;
- }
+ Assert(events != NULL);
+ while(low+1 < high) {
+ uintnat m = (low+high)/2;
+ if(pc < events[m].ev_pc) high = m;
+ else low = m;
}
- if (best_ev != 0) return best_ev;
- return Val_false;
+ if(events[low].ev_pc == pc)
+ return low;
+ /* ocamlc sometimes moves an event past a following PUSH instruction;
+ allow mismatch by 1 instruction. */
+ if(events[low].ev_pc == pc + 1)
+ return low;
+ if(low+1 < n_events && events[low+1].ev_pc == pc + 1)
+ return low+1;
+ return -1;
}
/* Extract location information for the given PC */
@@ -277,28 +353,21 @@ struct loc_info {
int loc_endchr;
};
-static void extract_location_info(value events, code_t pc,
+static void extract_location_info(code_t pc,
/*out*/ struct loc_info * li)
{
- value ev, ev_start;
-
- ev = event_for_location(events, pc);
+ intnat ev = event_for_location(pc);
li->loc_is_raise = caml_is_instruction(*pc, RAISE) ||
caml_is_instruction(*pc, RERAISE);
- if (ev == Val_false) {
+ if (ev == -1) {
li->loc_valid = 0;
return;
}
li->loc_valid = 1;
- ev_start = Field (Field (ev, EV_LOC), LOC_START);
- li->loc_filename = String_val (Field (ev_start, POS_FNAME));
- li->loc_lnum = Int_val (Field (ev_start, POS_LNUM));
- li->loc_startchr =
- Int_val (Field (ev_start, POS_CNUM))
- - Int_val (Field (ev_start, POS_BOL));
- li->loc_endchr =
- Int_val (Field (Field (Field (ev, EV_LOC), LOC_END), POS_CNUM))
- - Int_val (Field (ev_start, POS_BOL));
+ li->loc_filename = events[ev].ev_filename;
+ li->loc_lnum = events[ev].ev_lnum;
+ li->loc_startchr = events[ev].ev_startchr;
+ li->loc_endchr = events[ev].ev_endchr;
}
/* Print location information -- same behavior as in Printexc */
@@ -335,55 +404,47 @@ static void print_location(struct loc_info * li, int index)
CAMLexport void caml_print_exception_backtrace(void)
{
- value events;
int i;
struct loc_info li;
- events = read_debug_info();
- if (events == Val_false) {
+ read_debug_info();
+ if (events == NULL) {
fprintf(stderr, "(Cannot print stack backtrace: %s)\n",
read_debug_info_error);
return;
}
for (i = 0; i < caml_backtrace_pos; i++) {
- extract_location_info(events, caml_backtrace_buffer[i], &li);
+ extract_location_info(caml_backtrace_buffer[i], &li);
print_location(&li, i);
}
}
/* Convert the backtrace to a data structure usable from OCaml */
-CAMLprim value caml_convert_raw_backtrace(value backtrace)
-{
- CAMLparam1(backtrace);
- CAMLlocal5(events, res, arr, p, fname);
- int i;
+CAMLprim value caml_convert_raw_backtrace_slot(value backtrace_slot) {
+ CAMLparam1(backtrace_slot);
+ CAMLlocal2(p, fname);
struct loc_info li;
- events = read_debug_info();
- if (events == Val_false) {
- res = Val_int(0); /* None */
+ read_debug_info();
+ if (events == NULL)
+ caml_failwith(read_debug_info_error);
+
+ extract_location_info(Codet_Val(backtrace_slot), &li);
+
+ if (li.loc_valid) {
+ fname = caml_copy_string(li.loc_filename);
+ p = caml_alloc_small(5, 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);
} else {
- arr = caml_alloc(Wosize_val(backtrace), 0);
- for (i = 0; i < Wosize_val(backtrace); i++) {
- extract_location_info(events, (code_t)Field(backtrace, i), &li);
- if (li.loc_valid) {
- fname = caml_copy_string(li.loc_filename);
- p = caml_alloc_small(5, 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);
- } else {
- p = caml_alloc_small(1, 1);
- Field(p, 0) = Val_bool(li.loc_is_raise);
- }
- caml_modify(&Field(arr, i), p);
- }
- res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */
+ p = caml_alloc_small(1, 1);
+ Field(p, 0) = Val_bool(li.loc_is_raise);
}
- CAMLreturn(res);
+ CAMLreturn(p);
}
/* Get a copy of the latest backtrace */
@@ -392,20 +453,49 @@ CAMLprim value caml_get_exception_raw_backtrace(value unit)
{
CAMLparam0();
CAMLlocal1(res);
- res = caml_alloc(caml_backtrace_pos, Abstract_tag);
- if(caml_backtrace_buffer != NULL)
- memcpy(&Field(res, 0), caml_backtrace_buffer,
- caml_backtrace_pos * sizeof(code_t));
+
+ res = caml_alloc(caml_backtrace_pos, 0);
+ if(caml_backtrace_buffer != NULL) {
+ intnat i;
+ for(i = 0; i < caml_backtrace_pos; i++)
+ Field(res, i) = Val_Codet(caml_backtrace_buffer[i]);
+ }
CAMLreturn(res);
}
-/* the function below is deprecated: see asmrun/backtrace.c */
+/* 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();
- CAMLlocal2(raw, res);
- raw = caml_get_exception_raw_backtrace(unit);
- res = caml_convert_raw_backtrace(raw);
+ CAMLlocal4(arr, raw_slot, slot, res);
+
+ read_debug_info();
+ if (events == NULL) {
+ res = Val_int(0); /* None */
+ } else {
+ arr = caml_alloc(caml_backtrace_pos, 0);
+ if(caml_backtrace_buffer == NULL) {
+ Assert(caml_backtrace_pos == 0);
+ } else {
+ intnat i;
+ for(i = 0; i < caml_backtrace_pos; i++) {
+ raw_slot = Val_Codet(caml_backtrace_buffer[i]);
+ /* caml_convert_raw_backtrace_slot will not fail with
+ caml_failwith as we checked (events != NULL) already */
+ slot = caml_convert_raw_backtrace_slot(raw_slot);
+ caml_modify(&Field(arr, i), slot);
+ }
+ }
+ res = caml_alloc_small(1, 0); Field(res, 0) = arr; /* Some */
+ }
CAMLreturn(res);
}
diff --git a/byterun/extern.c b/byterun/extern.c
index 33fa89a913..deb8209bad 100644
--- a/byterun/extern.c
+++ b/byterun/extern.c
@@ -75,10 +75,10 @@ static struct extern_item * extern_stack_limit = extern_stack_init
/* Forward declarations */
-static void extern_out_of_memory(void);
-static void extern_invalid_argument(char *msg);
-static void extern_failwith(char *msg);
-static void extern_stack_overflow(void);
+static void extern_out_of_memory(void) Noreturn;
+static void extern_invalid_argument(char *msg) Noreturn;
+static void extern_failwith(char *msg) Noreturn;
+static void extern_stack_overflow(void) Noreturn;
static struct code_fragment * extern_find_code(char *addr);
static void extern_replay_trail(void);
static void free_extern_output(void);
diff --git a/byterun/fail.c b/byterun/fail.c
index 530ca5d138..148e47a994 100644
--- a/byterun/fail.c
+++ b/byterun/fail.c
@@ -71,11 +71,9 @@ CAMLexport void caml_raise_with_args(value tag, int nargs, value args[])
CAMLexport void caml_raise_with_string(value tag, char const *msg)
{
- CAMLparam1 (tag);
- CAMLlocal1 (vmsg);
-
- vmsg = caml_copy_string(msg);
- caml_raise_with_arg(tag, vmsg);
+ CAMLparam1(tag);
+ value v_msg = caml_copy_string(msg);
+ caml_raise_with_arg(tag, v_msg);
CAMLnoreturn;
}
diff --git a/byterun/fix_code.c b/byterun/fix_code.c
index 746f8b7500..3380dc9195 100644
--- a/byterun/fix_code.c
+++ b/byterun/fix_code.c
@@ -98,10 +98,10 @@ char * caml_instr_base;
void caml_thread_code (code_t code, asize_t len)
{
code_t p;
- int l [STOP + 1];
+ int l [FIRST_UNIMPLEMENTED_OP];
int i;
- for (i = 0; i <= STOP; i++) {
+ for (i = 0; i < FIRST_UNIMPLEMENTED_OP; i++) {
l [i] = 0;
}
/* Instructions with one operand */
@@ -125,7 +125,7 @@ void caml_thread_code (code_t code, asize_t len)
len /= sizeof(opcode_t);
for (p = code; p < code + len; /*nothing*/) {
opcode_t instr = *p;
- if (instr < 0 || instr > STOP){
+ 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);
diff --git a/byterun/hash.c b/byterun/hash.c
index 3beb0e016e..f8964265db 100644
--- a/byterun/hash.c
+++ b/byterun/hash.c
@@ -172,6 +172,8 @@ CAMLexport uint32 caml_hash_mix_string(uint32 h, value s)
/* Maximal size of the queue used for breadth-first traversal. */
#define HASH_QUEUE_SIZE 256
+/* Maximal number of Forward_tag links followed in one step */
+#define MAX_FORWARD_DEREFERENCE 1000
/* The generic hash function */
@@ -213,7 +215,7 @@ CAMLprim value caml_hash(value count, value limit, value seed, value obj)
for (i = 0, len = Wosize_val(v) / Double_wosize; i < len; i++) {
h = caml_hash_mix_double(h, Double_field(v, i));
num--;
- if (num < 0) break;
+ if (num <= 0) break;
}
break;
case Abstract_tag:
@@ -226,8 +228,15 @@ CAMLprim value caml_hash(value count, value limit, value seed, value obj)
v = v - Infix_offset_val(v);
goto again;
case Forward_tag:
- v = Forward_val(v);
- goto again;
+ /* PR#6361: we can have a loop here, so limit the number of
+ Forward_tag links being followed */
+ for (i = MAX_FORWARD_DEREFERENCE; i > 0; i--) {
+ v = Forward_val(v);
+ if (Is_long(v) || !Is_in_value_area(v) || Tag_val(v) != Forward_tag)
+ goto again;
+ }
+ /* Give up on this object and move to the next */
+ break;
case Object_tag:
h = caml_hash_mix_intnat(h, Oid_val(v));
num--;
diff --git a/byterun/instruct.h b/byterun/instruct.h
index a643b0f935..f9cc80ee65 100644
--- a/byterun/instruct.h
+++ b/byterun/instruct.h
@@ -40,7 +40,6 @@ enum instructions {
GETSTRINGCHAR, SETSTRINGCHAR,
BRANCH, BRANCHIF, BRANCHIFNOT, SWITCH, BOOLNOT,
PUSHTRAP, POPTRAP, RAISE,
- RERAISE, RAISE_NOTRACE,
CHECK_SIGNALS,
C_CALL1, C_CALL2, C_CALL3, C_CALL4, C_CALL5, C_CALLN,
CONST0, CONST1, CONST2, CONST3, CONSTINT,
@@ -55,7 +54,9 @@ enum instructions {
BULTINT, BUGEINT,
GETPUBMET, GETDYNMET,
STOP,
- EVENT, BREAK
-};
+ EVENT, BREAK,
+ RERAISE, RAISE_NOTRACE,
+FIRST_UNIMPLEMENTED_OP};
+
#endif /* CAML_INSTRUCT_H */
diff --git a/byterun/interp.c b/byterun/interp.c
index a0e54d166a..9b682ba6ea 100644
--- a/byterun/interp.c
+++ b/byterun/interp.c
@@ -523,10 +523,21 @@ value caml_interprete(code_t prog, asize_t prog_size)
int nvars = *pc++;
int i;
if (nvars > 0) *--sp = accu;
- Alloc_small(accu, 1 + nvars, Closure_tag);
+ 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++;
- for (i = 0; i < nvars; i++) Field(accu, i + 1) = sp[i];
sp += nvars;
Next;
}
@@ -534,15 +545,25 @@ value caml_interprete(code_t prog, asize_t prog_size)
Instruct(CLOSUREREC): {
int nfuncs = *pc++;
int nvars = *pc++;
+ mlsize_t blksize = nfuncs * 2 - 1 + nvars;
int i;
value * p;
if (nvars > 0) *--sp = accu;
- Alloc_small(accu, nfuncs * 2 - 1 + nvars, Closure_tag);
- p = &Field(accu, nfuncs * 2 - 1);
- for (i = 0; i < nvars; i++) {
- *p++ = sp[i];
+ 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;
diff --git a/byterun/major_gc.c b/byterun/major_gc.c
index b3c25b8172..a44c8d90ad 100644
--- a/byterun/major_gc.c
+++ b/byterun/major_gc.c
@@ -27,6 +27,12 @@
#include "roots.h"
#include "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
+
uintnat caml_percent_free;
uintnat caml_major_heap_increment;
CAMLexport char *caml_heap_start;
@@ -82,7 +88,18 @@ static void realloc_gray_vals (void)
void caml_darken (value v, value *p /* not used */)
{
+#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS
+ if (Is_block (v) && Wosize_val (v) > 0) {
+ /* 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 (Hd_val (v)));
+#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){
@@ -124,6 +141,9 @@ static void mark_slice (intnat work)
value v, child;
header_t hd;
mlsize_t size, i;
+#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS
+ int marking_closure = 0;
+#endif
caml_gc_message (0x40, "Marking %ld words\n", work);
caml_gc_message (0x40, "Subphase = %ld\n", caml_gc_subphase);
@@ -132,13 +152,28 @@ static void mark_slice (intnat work)
if (gray_vals_ptr > gray_vals){
v = *--gray_vals_ptr;
hd = Hd_val(v);
+#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS
+ marking_closure =
+ (Tag_hd (hd) == Closure_tag || Tag_hd (hd) == Infix_tag);
+#endif
Assert (Is_gray_hd (hd));
Hd_val (v) = Blackhd_hd (hd);
size = Wosize_hd (hd);
if (Tag_hd (hd) < No_scan_tag){
for (i = 0; i < size; i++){
child = Field (v, i);
+#ifdef NATIVE_CODE_AND_NO_NAKED_POINTERS
+ if (Is_block (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. */
+ && (!marking_closure || Is_in_heap (child))) {
+ /* See [caml_darken] for a description of this assertion. */
+ CAMLassert (Is_in_heap (child) || Is_black_hd (Hd_val (child)));
+#else
if (Is_block (child) && Is_in_heap (child)) {
+#endif
hd = Hd_val (child);
if (Tag_hd (hd) == Forward_tag){
value f = Forward_val (child);
diff --git a/byterun/memory.h b/byterun/memory.h
index 0761070177..9befa873c1 100644
--- a/byterun/memory.h
+++ b/byterun/memory.h
@@ -266,27 +266,31 @@ CAMLextern struct caml__roots_block *caml_local_roots; /* defined in roots.c */
0)
#define CAMLlocal1(x) \
- value x = 0; \
+ value x = Val_unit; \
CAMLxparam1 (x)
#define CAMLlocal2(x, y) \
- value x = 0, y = 0; \
+ value x = Val_unit, y = Val_unit; \
CAMLxparam2 (x, y)
#define CAMLlocal3(x, y, z) \
- value x = 0, y = 0, z = 0; \
+ value x = Val_unit, y = Val_unit, z = Val_unit; \
CAMLxparam3 (x, y, z)
#define CAMLlocal4(x, y, z, t) \
- value x = 0, y = 0, z = 0, t = 0; \
+ 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 = 0, y = 0, z = 0, t = 0, u = 0; \
+ 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)] = { 0, /* 0, 0, ... */ }; \
+ 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))
diff --git a/byterun/misc.c b/byterun/misc.c
index 6dc27d5cc3..1872a80acd 100644
--- a/byterun/misc.c
+++ b/byterun/misc.c
@@ -26,7 +26,6 @@ int caml_failed_assert (char * expr, char * file, int line)
file, line, expr);
fflush (stderr);
exit (100);
- return 1; /* not reached */
}
void caml_set_fields (char *bp, unsigned long start, unsigned long filler)
diff --git a/byterun/misc.h b/byterun/misc.h
index 5640980a6f..f7b4fdc24a 100644
--- a/byterun/misc.h
+++ b/byterun/misc.h
@@ -64,7 +64,7 @@ typedef char * addr;
#ifdef DEBUG
#define CAMLassert(x) \
((x) ? (void) 0 : caml_failed_assert ( #x , __FILE__, __LINE__))
-CAMLextern int caml_failed_assert (char *, char *, int);
+CAMLextern int caml_failed_assert (char *, char *, int) Noreturn;
#else
#define CAMLassert(x) ((void) 0)
#endif
diff --git a/byterun/obj.c b/byterun/obj.c
index 1d7b57910b..b045fee263 100644
--- a/byterun/obj.c
+++ b/byterun/obj.c
@@ -255,3 +255,7 @@ CAMLprim value caml_set_oo_id (value obj) {
oo_last_id += 2;
return obj;
}
+
+CAMLprim value caml_int_as_pointer (value n) {
+ return n - 1;
+}
diff --git a/byterun/startup.c b/byterun/startup.c
index 89e296a720..3697220664 100644
--- a/byterun/startup.c
+++ b/byterun/startup.c
@@ -246,10 +246,10 @@ static int parse_command_line(char **argv)
#endif
case 'v':
if (!strcmp (argv[i], "-version")){
- printf ("The OCaml runtime, version " OCAML_VERSION "\n");
+ printf ("The OCaml runtime, version " OCAML_VERSION_STRING "\n");
exit (0);
}else if (!strcmp (argv[i], "-vnum")){
- printf (OCAML_VERSION "\n");
+ printf (OCAML_VERSION_STRING "\n");
exit (0);
}else{
caml_verb_gc = 0x001+0x004+0x008+0x010+0x020;
diff --git a/configure b/configure
index f2d312d558..74d489f10a 100755
--- a/configure
+++ b/configure
@@ -43,6 +43,7 @@ with_debugger=ocamldebugger
with_ocamldoc=ocamldoc
with_ocamlbuild=ocamlbuild
with_frame_pointers=false
+no_naked_pointers=false
TOOLPREF=""
with_cfi=true
@@ -150,6 +151,8 @@ while : ; do
with_ocamlbuild="";;
-with-frame-pointers|--with-frame-pointers)
with_frame_pointers=true;;
+ -no-naked-pointers|--no-naked-pointers)
+ no_naked_pointers=true;;
-no-cfi|--no-cfi)
with_cfi=false;;
*) err "Unknown option \"$1\".";;
@@ -757,11 +760,11 @@ if test $with_sharedlibs = "yes"; then
sparc*-*-linux*) natdynlink=true;;
i686-*-kfreebsd*) natdynlink=true;;
x86_64-*-kfreebsd*) natdynlink=true;;
- i[345]86-*-freebsd*) natdynlink=true;;
+ i[3456]86-*-freebsd*) natdynlink=true;;
x86_64-*-freebsd*) natdynlink=true;;
- i[345]86-*-openbsd*) natdynlink=true;;
+ i[3456]86-*-openbsd*) natdynlink=true;;
x86_64-*-openbsd*) natdynlink=true;;
- i[345]86-*-netbsd*) natdynlink=true;;
+ i[3456]86-*-netbsd*) natdynlink=true;;
x86_64-*-netbsd*) natdynlink=true;;
i386-*-gnu0.3) natdynlink=true;;
arm*-*-linux*) natdynlink=true;;
@@ -818,6 +821,8 @@ case "$target" in
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-*-freebsd*) arch=amd64; system=freebsd;;
@@ -886,8 +891,10 @@ case "$arch,$system" in
sparc,solaris) as="${TOOLPREF}as"
case "$cc" in
*gcc*) aspp="${TOOLPREF}gcc -c";;
- *) aspp="${TOOLPREF}as -P";;
+ *) aspp="${TOOLPREF}as -P";;
esac;;
+ *,freebsd) as="${TOOLPREF}as"
+ aspp="${TOOLPREF}cc -c";;
amd64,*|arm,*|arm64,*|i386,*|power,bsd*|sparc,*)
as="${TOOLPREF}as"
aspp="${TOOLPREF}gcc -c";;
@@ -903,12 +910,16 @@ case "$arch,$system" in
i386,bsd_elf) profiling='prof';;
amd64,macosx) profiling='prof';;
i386,macosx) profiling='prof';;
+ sparc,bsd) profiling='prof';;
sparc,solaris)
profiling='prof'
case "$nativecc" in gcc*) ;; *) cc_profile='-xpg';; esac;;
amd64,linux) profiling='prof';;
+ amd64,openbsd) profiling='prof';;
amd64,gnu) profiling='prof';;
arm,linux*) profiling='prof';;
+ power,elf) profiling='prof';;
+ power,bsd*) profiling='prof';;
*) profiling='noprof';;
esac
@@ -1289,6 +1300,11 @@ if test $nargs != "none"; then
echo "#define HAS_GETHOSTBYADDR_R $nargs" >> s.h
fi
+if sh ./hasgot mkstemp; then
+ inf "mkstemp() found"
+ echo "#define HAS_MKSTEMP" >> s.h
+fi
+
# Determine if the debugger is supported
if test -n "$with_debugger"; then
@@ -1600,6 +1616,9 @@ if test "$with_frame_pointers" = "true"; then
fi
+if $no_naked_pointers; then
+ echo "#define NO_NAKED_POINTERS" >> m.h
+fi
# Final twiddling of compiler options to work around known bugs
@@ -1736,7 +1755,11 @@ else
else
inf " with frame pointers....... no"
fi
- echo " native dynlink ........... $natdynlink"
+ if $no_naked_pointers; then
+ inf " naked pointers forbidden.. yes"
+ else
+ inf " naked pointers forbidden.. no"
+ fi
inf " native dynlink ........... $natdynlink"
if test "$profiling" = "prof"; then
inf " profiling with gprof ..... supported"
diff --git a/debugger/.depend b/debugger/.depend
index 13de8ede13..b62541619a 100644
--- a/debugger/.depend
+++ b/debugger/.depend
@@ -164,11 +164,13 @@ program_loading.cmx : unix_tools.cmx $(UNIXDIR)/unix.cmx \
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 \
- debugger_config.cmi breakpoints.cmi program_management.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 \
- debugger_config.cmx breakpoints.cmx program_management.cmi
+ ../typing/envaux.cmx debugger_config.cmx ../utils/config.cmx \
+ breakpoints.cmx 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
show_information.cmo : symbols.cmi source.cmi show_source.cmi printval.cmi \
diff --git a/debugger/Makefile.shared b/debugger/Makefile.shared
index 249e8b4c40..fed1d26dab 100644
--- a/debugger/Makefile.shared
+++ b/debugger/Makefile.shared
@@ -14,7 +14,7 @@ include ../config/Makefile
ROOTDIR=..
CAMLC=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib
-COMPFLAGS=-warn-error A $(INCLUDES)
+COMPFLAGS=-warn-error A -safe-string $(INCLUDES)
LINKFLAGS=-linkall -I $(UNIXDIR)
CAMLYACC=../boot/ocamlyacc
YACCFLAGS=
diff --git a/debugger/debugcom.ml b/debugger/debugcom.ml
index 72702da168..ac91df799f 100644
--- a/debugger/debugcom.ml
+++ b/debugger/debugcom.ml
@@ -187,10 +187,10 @@ let set_trap_barrier pos =
let value_size = if 1 lsl 31 = 0 then 4 else 8
let input_remote_value ic =
- Misc.input_bytes ic value_size
+ really_input_string ic value_size
let output_remote_value ic v =
- output ic v 0 value_size
+ output_substring ic v 0 value_size
exception Marshalling_error
@@ -244,7 +244,7 @@ module Remote_value =
if input_byte !conn.io_in = 0 then
Remote(input_remote_value !conn.io_in)
else begin
- let buf = Misc.input_bytes !conn.io_in 8 in
+ let buf = really_input_string !conn.io_in 8 in
let floatbuf = float n (* force allocation of a new float *) in
String.unsafe_blit buf 0 (Obj.magic floatbuf) 0 8;
Local(Obj.repr floatbuf)
diff --git a/debugger/input_handling.mli b/debugger/input_handling.mli
index 749687ce3b..66db47f15f 100644
--- a/debugger/input_handling.mli
+++ b/debugger/input_handling.mli
@@ -49,7 +49,7 @@ val current_prompt : string ref
(* Where the user input come from. *)
val user_channel : io_channel ref
-val read_user_input : string -> int -> int
+val read_user_input : bytes -> int -> int
(* Stop reading user input. *)
val stop_user_input : unit -> unit
diff --git a/debugger/program_management.ml b/debugger/program_management.ml
index 1e29b138f8..48118573ee 100644
--- a/debugger/program_management.ml
+++ b/debugger/program_management.ml
@@ -30,7 +30,7 @@ open Time_travel
let file_name = ref (None : string option)
(* Default connection handler. *)
-let buffer = String.create 1024
+let buffer = Bytes.create 1024
let control_connection pid fd =
if (read fd.io_fd buffer 0 1024) = 0 then
forget_process fd pid
diff --git a/debugger/source.ml b/debugger/source.ml
index c68df3373c..af69fbc7bf 100644
--- a/debugger/source.ml
+++ b/debugger/source.ml
@@ -74,7 +74,7 @@ let get_buffer pos mdle =
try List.assoc mdle !buffer_list with
Not_found ->
let inchan = open_in_bin (source_of_module pos mdle) in
- let content = Misc.input_bytes inchan (in_channel_length inchan) in
+ let content = really_input_string inchan (in_channel_length inchan) in
let buffer = (content, ref []) in
buffer_list :=
(list_truncate !buffer_max_count ((mdle, buffer)::!buffer_list));
diff --git a/driver/compenv.ml b/driver/compenv.ml
index a40083275b..32ecb937e9 100644
--- a/driver/compenv.ml
+++ b/driver/compenv.ml
@@ -55,7 +55,7 @@ let last_ppx = ref []
let first_objfiles = ref []
let last_objfiles = ref []
-(* Note: this function is duplicated in optcompile.ml *)
+(* Check validity of module name *)
let check_unit_name ppf filename name =
try
begin match name.[0] with
@@ -76,10 +76,19 @@ let check_unit_name ppf filename name =
with Exit -> ()
;;
-
-
-
-
+(* Compute name of module from output file name *)
+let module_of_filename ppf inputfile outputprefix =
+ let basename = Filename.basename outputprefix in
+ let name =
+ try
+ let pos = String.index basename '.' in
+ String.sub basename 0 pos
+ with Not_found -> basename
+ in
+ let name = String.capitalize name in
+ check_unit_name ppf inputfile name;
+ name
+;;
type readenv_position =
@@ -158,6 +167,7 @@ let read_OCAMLPARAM ppf position =
| "nolabels" -> set "nolabels" [ classic ] v
| "principal" -> set "principal" [ principal ] v
| "rectypes" -> set "rectypes" [ recursive_types ] v
+ | "safe-string" -> clear "safe-string" [ unsafe_string ] v
| "strict-sequence" -> set "strict-sequence" [ strict_sequence ] v
| "thread" -> set "thread" [ use_threads ] v
| "unsafe" -> set "unsafe" [ fast ] v
diff --git a/driver/compenv.mli b/driver/compenv.mli
index d1d64393ac..85d588ef6e 100644
--- a/driver/compenv.mli
+++ b/driver/compenv.mli
@@ -10,7 +10,8 @@
(* *)
(***********************************************************************)
-val check_unit_name : Format.formatter -> string -> string -> unit
+(* val check_unit_name : Format.formatter -> string -> string -> unit *)
+val module_of_filename : Format.formatter -> string -> string -> string
val output_prefix : string -> string
val extract_output : string option -> string
diff --git a/driver/compile.ml b/driver/compile.ml
index bc9201e266..fb003c7ea1 100644
--- a/driver/compile.ml
+++ b/driver/compile.ml
@@ -21,17 +21,17 @@ open Compenv
(* Keep in sync with the copy in optcompile.ml *)
+let tool_name = "ocamlc"
+
let interface ppf sourcefile outputprefix =
Compmisc.init_path false;
- let modulename =
- String.capitalize(Filename.basename(chop_extension_if_any sourcefile)) in
- check_unit_name ppf sourcefile modulename;
+ 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 ppf sourcefile 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;
- let tsg = Typemod.transl_signature initial_env ast in
+ let tsg = Typemod.type_interface 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
@@ -57,9 +57,7 @@ let (++) x f = f x
let implementation ppf sourcefile outputprefix =
Compmisc.init_path false;
- let modulename =
- String.capitalize(Filename.basename(chop_extension_if_any sourcefile)) in
- check_unit_name ppf sourcefile modulename;
+ let modulename = module_of_filename ppf sourcefile outputprefix in
Env.set_unit_name modulename;
let env = Compmisc.initial_env() in
if !Clflags.print_types then begin
@@ -74,7 +72,7 @@ let implementation ppf sourcefile outputprefix =
Warnings.check_fatal ();
Stypes.dump (Some (outputprefix ^ ".annot"))
in
- try comp (Pparse.parse_implementation ppf sourcefile)
+ try comp (Pparse.parse_implementation ~tool_name ppf sourcefile)
with x ->
Stypes.dump (Some (outputprefix ^ ".annot"));
raise x
@@ -99,7 +97,7 @@ let implementation ppf sourcefile outputprefix =
close_out oc;
Stypes.dump (Some (outputprefix ^ ".annot"))
in
- try comp (Pparse.parse_implementation ppf sourcefile)
+ try comp (Pparse.parse_implementation ~tool_name ppf sourcefile)
with x ->
close_out oc;
remove_file objfile;
diff --git a/driver/compmisc.ml b/driver/compmisc.ml
index 8f974f4be1..a2bc4b83a5 100644
--- a/driver/compmisc.ml
+++ b/driver/compmisc.ml
@@ -40,19 +40,21 @@ let init_path native =
toplevel initialization (PR#1775) *)
let open_implicit_module m env =
- try
- Env.open_pers_signature m env
- with Not_found ->
- Misc.fatal_error (Printf.sprintf "cannot open implicit module %S" m)
+ let open Asttypes in
+ let lid = {loc = Location.in_file "command line";
+ txt = Longident.Lident m } in
+ snd (Typemod.type_open_ Override env lid.loc lid)
let initial_env () =
Ident.reinit();
+ let initial =
+ if !Clflags.unsafe_string then Env.initial_unsafe_string
+ else Env.initial_safe_string
+ in
let env =
- if !Clflags.nopervasives
- then Env.initial
- else
- open_implicit_module "Pervasives" Env.initial
+ if !Clflags.nopervasives then initial else
+ open_implicit_module "Pervasives" initial
in
List.fold_left (fun env m ->
open_implicit_module m env
- ) env !implicit_modules
+ ) env (!implicit_modules @ List.rev !Clflags.open_modules)
diff --git a/driver/main.ml b/driver/main.ml
index cbb6459993..4b1c7264aa 100644
--- a/driver/main.ml
+++ b/driver/main.ml
@@ -85,6 +85,7 @@ module Options = Main_args.Make_bytecomp_options (struct
let _custom = set custom_runtime
let _dllib s = dllibs := Misc.rev_split_words s @ !dllibs
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 s = include_dirs := s :: !include_dirs
@@ -96,12 +97,14 @@ module Options = Main_args.Make_bytecomp_options (struct
let _linkall = set link_everything
let _make_runtime () =
custom_runtime := true; make_runtime := true; link_everything := true
+ let _no_alias_deps = set transparent_modules
let _no_app_funct = unset applicative_functors
let _noassert = set noassert
let _nolabels = set classic
let _noautolink = set no_auto_link
let _nostdlib = set no_std_include
let _o s = output_name := Some s
+ let _open s = open_modules := s :: !open_modules
let _output_obj () = output_c_object := true; custom_runtime := true
let _pack = set make_package
let _pp s = preprocessor := Some s
@@ -109,12 +112,13 @@ module Options = Main_args.Make_bytecomp_options (struct
let _principal = set principal
let _rectypes = set recursive_types
let _runtime_variant s = runtime_variant := s
+ let _safe_string = unset unsafe_string
let _short_paths = unset real_paths
let _strict_sequence = set strict_sequence
let _thread = set use_threads
- let _trans_mod = set transparent_modules
let _vmthread = set use_vmthreads
let _unsafe = set fast
+ let _unsafe_string = set unsafe_string
let _use_prims s = use_prims := s
let _use_runtime s = use_runtime := s
let _v () = print_version_and_library "compiler"
@@ -160,7 +164,8 @@ let main () =
Compmisc.init_path false;
let extracted_output = extract_output !output_name in
let revd = get_objfiles () in
- Bytepackager.package_files ppf revd (extracted_output);
+ Bytepackager.package_files ppf (Compmisc.initial_env ())
+ revd (extracted_output);
Warnings.check_fatal ();
end
else if not !compile_only && !objfiles <> [] then begin
diff --git a/driver/main_args.ml b/driver/main_args.ml
index ec97d6c983..dd04352ea3 100644
--- a/driver/main_args.ml
+++ b/driver/main_args.ml
@@ -73,9 +73,10 @@ let mk_dtypes f =
"-dtypes", Arg.Unit f, " (deprecated) same as -annot"
;;
-let mk_for_pack_byt () =
- "-for-pack", Arg.String ignore,
- "<ident> Ignored (for compatibility with ocamlopt)"
+let mk_for_pack_byt f =
+ "-for-pack", Arg.String f,
+ "<ident> Generate code that can later be `packed' with\n\
+ \ ocamlc -pack -o <ident>.cmo"
;;
let mk_for_pack_opt f =
@@ -150,10 +151,19 @@ let mk_modern f =
"-modern", Arg.Unit f, " (deprecated) same as -labels"
;;
+let mk_no_alias_deps f =
+ "-no-alias-deps", Arg.Unit f,
+ " Do not record dependencies for module aliases"
+;;
+
let mk_no_app_funct f =
"-no-app-funct", Arg.Unit f, " Deactivate applicative functors"
;;
+let mk_no_float_const_prop f =
+ "-no-float-const-prop", Arg.Unit f, " Deactivate constant propagation for floating-point operations"
+;;
+
let mk_noassert f =
"-noassert", Arg.Unit f, " Do not compile assertion checks"
;;
@@ -199,6 +209,9 @@ let mk_o f =
"-o", Arg.String f, "<file> Set output file name to <file>"
;;
+let mk_open f =
+ "-open", Arg.String f, "<module> Opens the module <module> before typing"
+
let mk_output_obj f =
"-output-obj", Arg.Unit f, " Output a C object file instead of an executable"
;;
@@ -243,6 +256,14 @@ let mk_S f =
"-S", Arg.Unit f, " Keep intermediate assembly file"
;;
+let mk_safe_string f =
+ "-safe-string", Arg.Unit f, " Make strings immutable"
+;;
+
+let mk_shared f =
+ "-shared", Arg.Unit f, " Produce a dynlinkable plugin"
+;;
+
let mk_short_paths f =
"-short-paths", Arg.Unit f, " Shorten paths in types"
;;
@@ -256,24 +277,20 @@ let mk_strict_sequence f =
" Left-hand part of a sequence must have type unit"
;;
-let mk_shared f =
- "-shared", Arg.Unit f, " Produce a dynlinkable plugin"
-;;
-
let mk_thread f =
"-thread", Arg.Unit f,
" Generate code that supports the system threads library"
;;
-let mk_trans_mod f =
- "-trans-mod", Arg.Unit f,
- " Make typing and linking only depend on normalized paths"
-
let mk_unsafe f =
"-unsafe", Arg.Unit f,
" Do not compile bounds checking on array and string access"
;;
+let mk_unsafe_string f =
+ "-unsafe-string", Arg.Unit f, " Make strings mutable (default)"
+;;
+
let mk_use_runtime f =
"-use-runtime", Arg.String f,
"<file> Generate bytecode for the given runtime system"
@@ -385,6 +402,10 @@ let mk_dcombine f =
"-dcombine", Arg.Unit f, " (undocumented)"
;;
+let mk_dcse f =
+ "-dcse", Arg.Unit f, " (undocumented)"
+;;
+
let mk_dlive f =
"-dlive", Arg.Unit f, " (undocumented)"
;;
@@ -430,222 +451,111 @@ let mk__ f =
"<file> Treat <file> as a file name (even if it starts with `-')"
;;
-module type Bytecomp_options = sig
- val _a : unit -> unit
+module type Common_options = sig
val _absname : unit -> unit
- val _annot : unit -> unit
- val _binannot : unit -> unit
- val _c : unit -> unit
- val _cc : string -> unit
- val _cclib : string -> unit
- val _ccopt : string -> unit
- val _compat_32 : unit -> unit
- val _config : unit -> unit
- val _custom : unit -> unit
- val _dllib : string -> unit
- val _dllpath : string -> unit
- val _g : unit -> unit
- val _i : unit -> unit
val _I : string -> unit
- val _impl : string -> unit
- val _intf : string -> unit
- val _intf_suffix : string -> unit
- val _keep_locs : unit -> unit
val _labels : unit -> unit
- val _linkall : unit -> unit
- val _make_runtime : unit -> unit
+ val _no_alias_deps : unit -> unit
val _no_app_funct : unit -> unit
val _noassert : unit -> unit
- val _noautolink : unit -> unit
val _nolabels : unit -> unit
val _nostdlib : unit -> unit
- val _o : string -> unit
- val _output_obj : unit -> unit
- val _pack : unit -> unit
- val _pp : string -> unit
+ val _open : string -> unit
val _ppx : string -> unit
val _principal : unit -> unit
val _rectypes : unit -> unit
- val _runtime_variant : string -> unit
+ val _safe_string : unit -> unit
val _short_paths : unit -> unit
val _strict_sequence : unit -> unit
- val _trans_mod : unit -> unit
- val _thread : unit -> unit
- val _vmthread : unit -> unit
val _unsafe : unit -> unit
- val _use_runtime : string -> unit
- val _v : unit -> unit
+ val _unsafe_string : unit -> unit
val _version : unit -> unit
val _vnum : unit -> unit
- val _verbose : unit -> unit
val _w : string -> unit
val _warn_error : string -> unit
val _warn_help : unit -> unit
- val _where : unit -> unit
- val _nopervasives : unit -> unit
- val _use_prims : string -> unit
val _dsource : unit -> unit
val _dparsetree : unit -> unit
val _dtypedtree : unit -> unit
val _drawlambda : unit -> unit
val _dlambda : unit -> unit
- val _dinstr : unit -> unit
val anonymous : string -> unit
end;;
-module type Bytetop_options = sig
- val _absname : unit -> unit
- val _I : string -> unit
- val _init : string -> unit
- val _labels : unit -> unit
- val _no_app_funct : unit -> unit
- val _noassert : unit -> unit
- val _noinit : unit -> unit
- val _nolabels : unit -> unit
- val _noprompt : unit -> unit
- val _nopromptcont : unit -> unit
- val _nostdlib : unit -> unit
- val _ppx : string -> unit
- val _principal : unit -> unit
- val _rectypes : unit -> unit
- val _short_paths : unit -> unit
- val _stdin: unit -> unit
- val _strict_sequence : unit -> unit
- val _trans_mod : unit -> unit
- val _unsafe : unit -> unit
- val _version : unit -> unit
- val _vnum : unit -> unit
- val _w : string -> unit
- val _warn_error : string -> unit
- val _warn_help : unit -> unit
-
- val _dsource : unit -> unit
- val _dparsetree : unit -> unit
- val _dtypedtree : unit -> unit
- val _drawlambda : unit -> unit
- val _dlambda : unit -> unit
- val _dinstr : unit -> unit
-
- val anonymous : string -> unit
-end;;
-
-module type Optcomp_options = sig
+module type Compiler_options = sig
val _a : unit -> unit
- val _absname : unit -> unit
val _annot : unit -> unit
val _binannot : unit -> unit
val _c : unit -> unit
val _cc : string -> unit
val _cclib : string -> unit
val _ccopt : string -> unit
- val _compact : unit -> unit
val _config : unit -> unit
val _for_pack : string -> unit
val _g : unit -> unit
val _i : unit -> unit
- val _I : string -> unit
val _impl : string -> unit
- val _inline : int -> unit
val _intf : string -> unit
val _intf_suffix : string -> unit
val _keep_locs : unit -> unit
- val _labels : unit -> unit
val _linkall : unit -> unit
- val _no_app_funct : unit -> unit
- val _noassert : unit -> unit
val _noautolink : unit -> unit
- val _nodynlink : unit -> unit
- val _nolabels : unit -> unit
- val _nostdlib : unit -> unit
val _o : string -> unit
val _output_obj : unit -> unit
- val _p : unit -> unit
val _pack : unit -> unit
val _pp : string -> unit
- val _ppx : string -> unit
val _principal : unit -> unit
val _rectypes : unit -> unit
val _runtime_variant : string -> unit
- val _S : unit -> unit
- val _shared : unit -> unit
+ val _safe_string : unit -> unit
val _short_paths : unit -> unit
- val _strict_sequence : unit -> unit
- val _trans_mod : unit -> unit
val _thread : unit -> unit
- val _unsafe : unit -> unit
val _v : unit -> unit
val _verbose : unit -> unit
- val _version : unit -> unit
- val _vnum : unit -> unit
- val _w : string -> unit
- val _warn_error : string -> unit
- val _warn_help : unit -> unit
val _where : unit -> unit
val _nopervasives : unit -> unit
- val _dsource : unit -> unit
- val _dparsetree : unit -> unit
- val _dtypedtree : unit -> unit
- val _drawlambda : unit -> unit
- val _dlambda : unit -> unit
- val _dclambda : unit -> unit
- val _dcmm : unit -> unit
- val _dsel : unit -> unit
- val _dcombine : unit -> unit
- val _dlive : unit -> unit
- val _dspill : unit -> unit
- val _dsplit : unit -> unit
- val _dinterf : unit -> unit
- val _dprefer : unit -> unit
- val _dalloc : unit -> unit
- val _dreload : unit -> unit
- val _dscheduling : unit -> unit
- val _dlinear : unit -> unit
- val _dstartup : unit -> unit
+end
+;;
- val anonymous : string -> unit
+module type Bytecomp_options = sig
+ include Common_options
+ include Compiler_options
+ val _compat_32 : unit -> unit
+ val _custom : unit -> unit
+ val _dllib : string -> unit
+ val _dllpath : string -> unit
+ val _make_runtime : unit -> unit
+ val _vmthread : unit -> unit
+ val _use_runtime : string -> unit
+
+ val _dinstr : unit -> unit
+
+ val _use_prims : string -> unit
end;;
-module type Opttop_options = sig
- val _absname : unit -> unit
- val _compact : unit -> unit
- val _I : string -> unit
+module type Bytetop_options = sig
+ include Common_options
val _init : string -> unit
- val _inline : int -> unit
- val _labels : unit -> unit
- val _no_app_funct : unit -> unit
- val _noassert : unit -> unit
val _noinit : unit -> unit
- val _nolabels : unit -> unit
val _noprompt : unit -> unit
val _nopromptcont : unit -> unit
- val _nostdlib : unit -> unit
- val _ppx : string -> unit
- val _principal : unit -> unit
- val _rectypes : unit -> unit
- val _S : unit -> unit
- val _short_paths : unit -> unit
val _stdin : unit -> unit
- val _strict_sequence : unit -> unit
- val _trans_mod : unit -> unit
- val _unsafe : unit -> unit
- val _version : unit -> unit
- val _vnum : unit -> unit
- val _w : string -> unit
- val _warn_error : string -> unit
- val _warn_help : unit -> unit
- val _dsource : unit -> unit
- val _dparsetree : unit -> unit
- val _dtypedtree : unit -> unit
- val _drawlambda : unit -> unit
- val _dlambda : unit -> unit
+ val _dinstr : unit -> unit
+end;;
+
+module type Optcommon_options = sig
+ val _compact : unit -> unit
+ val _inline : int -> unit
+
val _dclambda : unit -> unit
val _dcmm : unit -> unit
val _dsel : unit -> unit
val _dcombine : unit -> unit
+ val _dcse : unit -> unit
val _dlive : unit -> unit
val _dspill : unit -> unit
val _dsplit : unit -> unit
@@ -656,8 +566,29 @@ module type Opttop_options = sig
val _dscheduling : unit -> unit
val _dlinear : unit -> unit
val _dstartup : unit -> unit
+end;;
- val anonymous : string -> unit
+module type Optcomp_options = sig
+ include Common_options
+ include Compiler_options
+ include Optcommon_options
+ val _no_float_const_prop : unit -> unit
+ val _nodynlink : unit -> unit
+ val _p : unit -> unit
+ val _pp : string -> unit
+ val _S : unit -> unit
+ val _shared : unit -> unit
+end;;
+
+module type Opttop_options = sig
+ include Common_options
+ include Optcommon_options
+ val _init : string -> unit
+ val _noinit : unit -> unit
+ val _noprompt : unit -> unit
+ val _nopromptcont : unit -> unit
+ val _S : unit -> unit
+ val _stdin : unit -> unit
end;;
module type Arg_list = sig
@@ -681,7 +612,7 @@ struct
mk_dllib F._dllib;
mk_dllpath F._dllpath;
mk_dtypes F._annot;
- mk_for_pack_byt ();
+ mk_for_pack_byt F._for_pack;
mk_g_byt F._g;
mk_i F._i;
mk_I F._I;
@@ -695,12 +626,14 @@ struct
mk_make_runtime F._make_runtime;
mk_make_runtime_2 F._make_runtime;
mk_modern F._labels;
+ mk_no_alias_deps F._no_alias_deps;
mk_no_app_funct F._no_app_funct;
mk_noassert F._noassert;
mk_noautolink_byt F._noautolink;
mk_nolabels F._nolabels;
mk_nostdlib F._nostdlib;
mk_o F._o;
+ mk_open F._open;
mk_output_obj F._output_obj;
mk_pack_byt F._pack;
mk_pp F._pp;
@@ -708,11 +641,12 @@ struct
mk_principal F._principal;
mk_rectypes F._rectypes;
mk_runtime_variant F._runtime_variant;
+ mk_safe_string F._safe_string;
mk_short_paths F._short_paths;
mk_strict_sequence F._strict_sequence;
- mk_trans_mod F._trans_mod;
mk_thread F._thread;
mk_unsafe F._unsafe;
+ mk_unsafe_string F._unsafe_string;
mk_use_runtime F._use_runtime;
mk_use_runtime_2 F._use_runtime;
mk_v F._v;
@@ -744,6 +678,7 @@ struct
mk_I F._I;
mk_init F._init;
mk_labels F._labels;
+ mk_no_alias_deps F._no_alias_deps;
mk_no_app_funct F._no_app_funct;
mk_noassert F._noassert;
mk_noinit F._noinit;
@@ -751,14 +686,16 @@ struct
mk_noprompt F._noprompt;
mk_nopromptcont F._nopromptcont;
mk_nostdlib F._nostdlib;
+ mk_open F._open;
mk_ppx F._ppx;
mk_principal F._principal;
mk_rectypes F._rectypes;
+ mk_safe_string F._safe_string;
mk_short_paths F._short_paths;
mk_stdin F._stdin;
mk_strict_sequence F._strict_sequence;
- mk_trans_mod F._trans_mod;
mk_unsafe F._unsafe;
+ mk_unsafe_string F._unsafe_string;
mk_version F._version;
mk_vnum F._vnum;
mk_w F._w;
@@ -800,13 +737,16 @@ struct
mk_keep_locs F._keep_locs;
mk_labels F._labels;
mk_linkall F._linkall;
+ mk_no_alias_deps F._no_alias_deps;
mk_no_app_funct F._no_app_funct;
+ mk_no_float_const_prop F._no_float_const_prop;
mk_noassert F._noassert;
mk_noautolink_opt F._noautolink;
mk_nodynlink F._nodynlink;
mk_nolabels F._nolabels;
mk_nostdlib F._nostdlib;
mk_o F._o;
+ mk_open F._open;
mk_output_obj F._output_obj;
mk_p F._p;
mk_pack_opt F._pack;
@@ -816,12 +756,13 @@ struct
mk_rectypes F._rectypes;
mk_runtime_variant F._runtime_variant;
mk_S F._S;
+ mk_safe_string F._safe_string;
mk_shared F._shared;
mk_short_paths F._short_paths;
mk_strict_sequence F._strict_sequence;
- mk_trans_mod F._trans_mod;
mk_thread F._thread;
mk_unsafe F._unsafe;
+ mk_unsafe_string F._unsafe_string;
mk_v F._v;
mk_verbose F._verbose;
mk_version F._version;
@@ -842,6 +783,7 @@ struct
mk_dcmm F._dcmm;
mk_dsel F._dsel;
mk_dcombine F._dcombine;
+ mk_dcse F._dcse;
mk_dlive F._dlive;
mk_dspill F._dspill;
mk_dsplit F._dsplit;
@@ -863,6 +805,7 @@ module Make_opttop_options (F : Opttop_options) = struct
mk_init F._init;
mk_inline F._inline;
mk_labels F._labels;
+ mk_no_alias_deps F._no_alias_deps;
mk_no_app_funct F._no_app_funct;
mk_noassert F._noassert;
mk_noinit F._noinit;
@@ -870,15 +813,17 @@ module Make_opttop_options (F : Opttop_options) = struct
mk_noprompt F._noprompt;
mk_nopromptcont F._nopromptcont;
mk_nostdlib F._nostdlib;
+ mk_open F._open;
mk_ppx F._ppx;
mk_principal F._principal;
mk_rectypes F._rectypes;
mk_S F._S;
+ mk_safe_string F._safe_string;
mk_short_paths F._short_paths;
mk_stdin F._stdin;
mk_strict_sequence F._strict_sequence;
- mk_trans_mod F._trans_mod;
mk_unsafe F._unsafe;
+ mk_unsafe_string F._unsafe_string;
mk_version F._version;
mk_vnum F._vnum;
mk_w F._w;
@@ -894,6 +839,7 @@ module Make_opttop_options (F : Opttop_options) = struct
mk_dcmm F._dcmm;
mk_dsel F._dsel;
mk_dcombine F._dcombine;
+ mk_dcse F._dcse;
mk_dlive F._dlive;
mk_dspill F._dspill;
mk_dsplit F._dsplit;
diff --git a/driver/main_args.mli b/driver/main_args.mli
index 67a6c681d2..e4a9c58f5e 100644
--- a/driver/main_args.mli
+++ b/driver/main_args.mli
@@ -10,93 +10,24 @@
(* *)
(***********************************************************************)
-module type Bytecomp_options =
- sig
- val _a : unit -> unit
- val _absname : unit -> unit
- val _annot : unit -> unit
- val _binannot : unit -> unit
- val _c : unit -> unit
- val _cc : string -> unit
- val _cclib : string -> unit
- val _ccopt : string -> unit
- val _compat_32 : unit -> unit
- val _config : unit -> unit
- val _custom : unit -> unit
- val _dllib : string -> unit
- val _dllpath : string -> unit
- val _g : unit -> unit
- val _i : unit -> unit
- val _I : string -> unit
- val _impl : string -> unit
- val _intf : string -> unit
- val _intf_suffix : string -> unit
- val _keep_locs : unit -> unit
- val _labels : unit -> unit
- val _linkall : unit -> unit
- val _make_runtime : unit -> unit
- val _no_app_funct : unit -> unit
- val _noassert : unit -> unit
- val _noautolink : unit -> unit
- val _nolabels : unit -> unit
- val _nostdlib : unit -> unit
- val _o : string -> unit
- val _output_obj : unit -> unit
- val _pack : unit -> unit
- val _pp : string -> unit
- val _ppx : string -> unit
- val _principal : unit -> unit
- val _rectypes : unit -> unit
- val _runtime_variant : string -> unit
- val _short_paths : unit -> unit
- val _strict_sequence : unit -> unit
- val _trans_mod : unit -> unit
- val _thread : unit -> unit
- val _vmthread : unit -> unit
- val _unsafe : unit -> unit
- val _use_runtime : string -> unit
- val _v : unit -> unit
- val _version : unit -> unit
- val _vnum : unit -> unit
- val _verbose : unit -> unit
- val _w : string -> unit
- val _warn_error : string -> unit
- val _warn_help : unit -> unit
- val _where : unit -> unit
-
- val _nopervasives : unit -> unit
- val _use_prims : string -> unit
- val _dsource : unit -> unit
- val _dparsetree : unit -> unit
- val _dtypedtree : unit -> unit
- val _drawlambda : unit -> unit
- val _dlambda : unit -> unit
- val _dinstr : unit -> unit
-
- val anonymous : string -> unit
- end
-;;
-
-module type Bytetop_options = sig
+module type Common_options = sig
val _absname : unit -> unit
val _I : string -> unit
- val _init : string -> unit
val _labels : unit -> unit
+ val _no_alias_deps : unit -> unit
val _no_app_funct : unit -> unit
val _noassert : unit -> unit
- val _noinit : unit -> unit
val _nolabels : unit -> unit
- val _noprompt : unit -> unit
- val _nopromptcont : unit -> unit
val _nostdlib : unit -> unit
+ val _open : string -> unit
val _ppx : string -> unit
val _principal : unit -> unit
val _rectypes : unit -> unit
+ val _safe_string : unit -> unit
val _short_paths : unit -> unit
- val _stdin : unit -> unit
val _strict_sequence : unit -> unit
- val _trans_mod : unit -> unit
val _unsafe : unit -> unit
+ val _unsafe_string : unit -> unit
val _version : unit -> unit
val _vnum : unit -> unit
val _w : string -> unit
@@ -108,126 +39,82 @@ module type Bytetop_options = sig
val _dtypedtree : unit -> unit
val _drawlambda : unit -> unit
val _dlambda : unit -> unit
- val _dinstr : unit -> unit
val anonymous : string -> unit
-end;;
+end
-module type Optcomp_options = sig
+module type Compiler_options = sig
val _a : unit -> unit
- val _absname : unit -> unit
val _annot : unit -> unit
val _binannot : unit -> unit
val _c : unit -> unit
val _cc : string -> unit
val _cclib : string -> unit
val _ccopt : string -> unit
- val _compact : unit -> unit
val _config : unit -> unit
val _for_pack : string -> unit
val _g : unit -> unit
val _i : unit -> unit
- val _I : string -> unit
val _impl : string -> unit
- val _inline : int -> unit
val _intf : string -> unit
val _intf_suffix : string -> unit
val _keep_locs : unit -> unit
- val _labels : unit -> unit
val _linkall : unit -> unit
- val _no_app_funct : unit -> unit
- val _noassert : unit -> unit
val _noautolink : unit -> unit
- val _nodynlink : unit -> unit
- val _nolabels : unit -> unit
- val _nostdlib : unit -> unit
val _o : string -> unit
val _output_obj : unit -> unit
- val _p : unit -> unit
val _pack : unit -> unit
val _pp : string -> unit
- val _ppx : string -> unit
val _principal : unit -> unit
val _rectypes : unit -> unit
val _runtime_variant : string -> unit
- val _S : unit -> unit
- val _shared : unit -> unit
+ val _safe_string : unit -> unit
val _short_paths : unit -> unit
- val _strict_sequence : unit -> unit
- val _trans_mod : unit -> unit
val _thread : unit -> unit
- val _unsafe : unit -> unit
val _v : unit -> unit
val _verbose : unit -> unit
- val _version : unit -> unit
- val _vnum : unit -> unit
- val _w : string -> unit
- val _warn_error : string -> unit
- val _warn_help : unit -> unit
val _where : unit -> unit
val _nopervasives : unit -> unit
- val _dsource : unit -> unit
- val _dparsetree : unit -> unit
- val _dtypedtree : unit -> unit
- val _drawlambda : unit -> unit
- val _dlambda : unit -> unit
- val _dclambda : unit -> unit
- val _dcmm : unit -> unit
- val _dsel : unit -> unit
- val _dcombine : unit -> unit
- val _dlive : unit -> unit
- val _dspill : unit -> unit
- val _dsplit : unit -> unit
- val _dinterf : unit -> unit
- val _dprefer : unit -> unit
- val _dalloc : unit -> unit
- val _dreload : unit -> unit
- val _dscheduling : unit -> unit
- val _dlinear : unit -> unit
- val _dstartup : unit -> unit
+end
+;;
- val anonymous : string -> unit
+module type Bytecomp_options = sig
+ include Common_options
+ include Compiler_options
+ val _compat_32 : unit -> unit
+ val _custom : unit -> unit
+ val _dllib : string -> unit
+ val _dllpath : string -> unit
+ val _make_runtime : unit -> unit
+ val _vmthread : unit -> unit
+ val _use_runtime : string -> unit
+
+ val _dinstr : unit -> unit
+
+ val _use_prims : string -> unit
end;;
-module type Opttop_options = sig
- val _absname : unit -> unit
- val _compact : unit -> unit
- val _I : string -> unit
+module type Bytetop_options = sig
+ include Common_options
val _init : string -> unit
- val _inline : int -> unit
- val _labels : unit -> unit
- val _no_app_funct : unit -> unit
- val _noassert : unit -> unit
val _noinit : unit -> unit
- val _nolabels : unit -> unit
val _noprompt : unit -> unit
val _nopromptcont : unit -> unit
- val _nostdlib : unit -> unit
- val _ppx : string -> unit
- val _principal : unit -> unit
- val _rectypes : unit -> unit
- val _S : unit -> unit
- val _short_paths : unit -> unit
val _stdin : unit -> unit
- val _strict_sequence : unit -> unit
- val _trans_mod : unit -> unit
- val _unsafe : unit -> unit
- val _version : unit -> unit
- val _vnum : unit -> unit
- val _w : string -> unit
- val _warn_error : string -> unit
- val _warn_help : unit -> unit
- val _dsource : unit -> unit
- val _dparsetree : unit -> unit
- val _dtypedtree : unit -> unit
- val _drawlambda : unit -> unit
- val _dlambda : unit -> unit
+ val _dinstr : unit -> unit
+end;;
+
+module type Optcommon_options = sig
+ val _compact : unit -> unit
+ val _inline : int -> unit
+
val _dclambda : unit -> unit
val _dcmm : unit -> unit
val _dsel : unit -> unit
val _dcombine : unit -> unit
+ val _dcse : unit -> unit
val _dlive : unit -> unit
val _dspill : unit -> unit
val _dsplit : unit -> unit
@@ -238,8 +125,29 @@ module type Opttop_options = sig
val _dscheduling : unit -> unit
val _dlinear : unit -> unit
val _dstartup : unit -> unit
+end;;
- val anonymous : string -> unit
+module type Optcomp_options = sig
+ include Common_options
+ include Compiler_options
+ include Optcommon_options
+ val _no_float_const_prop : unit -> unit
+ val _nodynlink : unit -> unit
+ val _p : unit -> unit
+ val _pp : string -> unit
+ val _S : unit -> unit
+ val _shared : unit -> unit
+end;;
+
+module type Opttop_options = sig
+ include Common_options
+ include Optcommon_options
+ val _init : string -> unit
+ val _noinit : unit -> unit
+ val _noprompt : unit -> unit
+ val _nopromptcont : unit -> unit
+ val _S : unit -> unit
+ val _stdin : unit -> unit
end;;
module type Arg_list = sig
diff --git a/driver/optcompile.ml b/driver/optcompile.ml
index 625c0223e7..f0ef78d1cb 100644
--- a/driver/optcompile.ml
+++ b/driver/optcompile.ml
@@ -22,17 +22,17 @@ open Compenv
(* Keep in sync with the copy in compile.ml *)
+let tool_name = "ocamlopt"
+
let interface ppf sourcefile outputprefix =
Compmisc.init_path false;
- let modulename =
- String.capitalize(Filename.basename(chop_extension_if_any sourcefile)) in
- check_unit_name ppf sourcefile modulename;
+ 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 ppf sourcefile 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;
- let tsg = Typemod.transl_signature initial_env ast in
+ let tsg = Typemod.type_interface 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
@@ -59,9 +59,7 @@ let (+++) (x, y) f = (x, f y)
let implementation ppf sourcefile outputprefix =
Compmisc.init_path true;
- let modulename =
- String.capitalize(Filename.basename(chop_extension_if_any sourcefile)) in
- check_unit_name ppf sourcefile modulename;
+ 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;
@@ -94,7 +92,7 @@ let implementation ppf sourcefile outputprefix =
Warnings.check_fatal ();
Stypes.dump (Some (outputprefix ^ ".annot"))
in
- try comp (Pparse.parse_implementation ppf sourcefile)
+ try comp (Pparse.parse_implementation ~tool_name ppf sourcefile)
with x ->
Stypes.dump (Some (outputprefix ^ ".annot"));
remove_file objfile;
diff --git a/driver/optmain.ml b/driver/optmain.ml
index d04ad76b19..a520a8ce14 100644
--- a/driver/optmain.ml
+++ b/driver/optmain.ml
@@ -93,13 +93,16 @@ module Options = Main_args.Make_optcomp_options (struct
let _keep_locs = set keep_locs
let _labels = clear classic
let _linkall = set link_everything
+ let _no_alias_deps = set transparent_modules
let _no_app_funct = clear applicative_functors
+ let _no_float_const_prop = clear float_const_prop
let _noassert = set noassert
let _noautolink = set no_auto_link
let _nodynlink = clear dlcode
let _nolabels = set classic
let _nostdlib = set no_std_include
let _o s = output_name := Some s
+ let _open s = open_modules := s :: !open_modules
let _output_obj = set output_c_object
let _p = set gprofile
let _pack = set make_package
@@ -108,13 +111,14 @@ module Options = Main_args.Make_optcomp_options (struct
let _principal = set principal
let _rectypes = set recursive_types
let _runtime_variant s = runtime_variant := s
+ let _safe_string = clear unsafe_string
let _short_paths = clear real_paths
let _strict_sequence = set strict_sequence
- let _trans_mod = set transparent_modules
let _shared () = shared := true; dlcode := true
let _S = set keep_asm_file
let _thread = set use_threads
let _unsafe = set fast
+ let _unsafe_string = set unsafe_string
let _v () = print_version_and_library "native-code compiler"
let _version () = print_version_string ()
let _vnum () = print_version_string ()
@@ -134,6 +138,7 @@ module Options = Main_args.Make_optcomp_options (struct
let _dcmm = set dump_cmm
let _dsel = set dump_selection
let _dcombine = set dump_combine
+ let _dcse = set dump_cse
let _dlive () = dump_live := true; Printmach.print_live := true
let _dspill = set dump_spill
let _dsplit = set dump_split
@@ -172,7 +177,8 @@ let main () =
else if !make_package then begin
Compmisc.init_path true;
let target = extract_output !output_name in
- Asmpackager.package_files ppf (get_objfiles ()) target;
+ Asmpackager.package_files ppf (Compmisc.initial_env ())
+ (get_objfiles ()) target;
Warnings.check_fatal ();
end
else if !shared then begin
diff --git a/driver/pparse.ml b/driver/pparse.ml
index 7f9974da7a..08b9bc736e 100644
--- a/driver/pparse.ml
+++ b/driver/pparse.ml
@@ -64,7 +64,7 @@ let apply_rewriter magic fn_in ppx =
(* check magic before passing to the next ppx *)
let ic = open_in_bin fn_out in
let buffer =
- try Misc.input_bytes ic (String.length magic) with End_of_file -> "" in
+ try really_input_string ic (String.length magic) with End_of_file -> "" in
close_in ic;
if buffer <> magic then begin
Misc.remove_file fn_out;
@@ -75,7 +75,7 @@ let apply_rewriter magic fn_in ppx =
let read_ast magic fn =
let ic = open_in_bin fn in
try
- let buffer = Misc.input_bytes ic (String.length magic) 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;
let ast = input_value ic in
@@ -87,25 +87,51 @@ let read_ast magic fn =
Misc.remove_file fn;
raise exn
-let apply_rewriters magic ast =
+let apply_rewriters ~tool_name magic ast =
+ let ctx = Ast_mapper.ppx_context ~tool_name () in
match !Clflags.all_ppx with
| [] -> ast
| ppxs ->
+ let ast =
+ if magic = Config.ast_impl_magic_number
+ then Obj.magic (Ast_helper.Str.attribute ctx :: (Obj.magic ast))
+ else Obj.magic (Ast_helper.Sig.attribute ctx :: (Obj.magic ast))
+ in
let fn =
List.fold_left (apply_rewriter magic) (write_ast magic ast)
(List.rev ppxs)
in
- read_ast magic fn
+ let ast = read_ast magic fn in
+ let open Parsetree in
+ if magic = Config.ast_impl_magic_number then
+ let ast =
+ match Obj.magic ast with
+ | {pstr_desc = Pstr_attribute({Location.txt = "ocaml.ppx.context"}, _)}
+ :: items ->
+ items
+ | items -> items
+ in
+ Obj.magic ast
+ else
+ let ast =
+ match Obj.magic ast with
+ | {psig_desc = Psig_attribute({Location.txt = "ocaml.ppx.context"}, _)}
+ :: items ->
+ items
+ | items -> items
+ in
+ Obj.magic ast
+
(* Parse a file or get a dumped syntax tree from it *)
exception Outdated_version
-let file ppf inputfile parse_fun ast_magic =
+let file ppf ~tool_name inputfile parse_fun ast_magic =
let ic = open_in_bin inputfile in
let is_ast_file =
try
- let buffer = Misc.input_bytes ic (String.length ast_magic) in
+ let buffer = really_input_string ic (String.length ast_magic) in
if buffer = ast_magic then true
else if String.sub buffer 0 9 = String.sub ast_magic 0 9 then
raise Outdated_version
@@ -134,7 +160,7 @@ let file ppf inputfile parse_fun ast_magic =
with x -> close_in ic; raise x
in
close_in ic;
- apply_rewriters ast_magic ast
+ apply_rewriters ~tool_name ast_magic ast
let report_error ppf = function
| CannotRun cmd ->
@@ -151,11 +177,11 @@ let () =
| _ -> None
)
-let parse_all parse_fun magic ppf sourcefile =
+let parse_all ~tool_name parse_fun magic ppf sourcefile =
Location.input_name := sourcefile;
let inputfile = preprocess sourcefile in
let ast =
- try file ppf inputfile parse_fun magic
+ try file ppf ~tool_name inputfile parse_fun magic
with exn ->
remove_preprocessed inputfile;
raise exn
@@ -163,7 +189,9 @@ let parse_all parse_fun magic ppf sourcefile =
remove_preprocessed inputfile;
ast
-let parse_implementation ppf sourcefile =
- parse_all Parse.implementation Config.ast_impl_magic_number ppf sourcefile
-let parse_interface ppf sourcefile =
- parse_all Parse.interface Config.ast_intf_magic_number ppf sourcefile
+let parse_implementation ppf ~tool_name sourcefile =
+ parse_all ~tool_name Parse.implementation
+ Config.ast_impl_magic_number ppf sourcefile
+let parse_interface ppf ~tool_name sourcefile =
+ parse_all ~tool_name Parse.interface
+ Config.ast_intf_magic_number ppf sourcefile
diff --git a/driver/pparse.mli b/driver/pparse.mli
index 6a53f3fa99..d45adf91de 100644
--- a/driver/pparse.mli
+++ b/driver/pparse.mli
@@ -20,10 +20,10 @@ exception Error of error
val preprocess : string -> string
val remove_preprocessed : string -> unit
-val file : formatter -> string -> (Lexing.lexbuf -> 'a) -> string -> 'a
-val apply_rewriters : string -> 'a -> 'a
+val file : formatter -> tool_name:string -> string -> (Lexing.lexbuf -> 'a) -> string -> 'a
+val apply_rewriters : tool_name:string -> string -> 'a -> 'a
val report_error : formatter -> error -> unit
-val parse_implementation: formatter -> string -> Parsetree.structure
-val parse_interface: formatter -> string -> Parsetree.signature
+val parse_implementation: formatter -> tool_name:string -> string -> Parsetree.structure
+val parse_interface: formatter -> tool_name:string -> string -> Parsetree.signature
diff --git a/lex/Makefile b/lex/Makefile
index e3cbd320be..cb5df8b41c 100644
--- a/lex/Makefile
+++ b/lex/Makefile
@@ -13,7 +13,7 @@
# The lexer generator
CAMLC=../boot/ocamlrun ../boot/ocamlc -strict-sequence -nostdlib -I ../boot
CAMLOPT=../boot/ocamlrun ../ocamlopt -nostdlib -I ../stdlib
-COMPFLAGS=-w +33..39 -warn-error A -bin-annot
+COMPFLAGS=-w +33..39 -warn-error A -bin-annot -safe-string
CAMLYACC=../boot/ocamlyacc
YACCFLAGS=-v
CAMLLEX=../boot/ocamlrun ../boot/ocamllex
diff --git a/lex/common.ml b/lex/common.ml
index 13b48fac6d..9b86ba111f 100644
--- a/lex/common.ml
+++ b/lex/common.ml
@@ -47,7 +47,7 @@ let update_tracker tr =
fprintf tr.oc "# %d \"%s\"\n" (tr.cur_line+1) tr.file;
;;
-let copy_buffer = String.create 1024
+let copy_buffer = Bytes.create 1024
let copy_chars_unix ic oc start stop =
let n = ref (stop - start) in
diff --git a/man/ocaml.m b/man/ocaml.m
index b393b771c1..6764d52ce3 100644
--- a/man/ocaml.m
+++ b/man/ocaml.m
@@ -133,6 +133,12 @@ window.
Do not include the standard library directory in the list of
directories searched for source and compiled files.
.TP
+.BI \-open \ module
+Opens the given module before starting the toplevel. If several
+.B \-open
+options are given, they are processed in order, just as if
+the statements open! module1;; ... open! moduleN;; were input.
+.TP
.BI \-ppx \ command
After parsing, pipe the abstract syntax tree through the preprocessor
.IR command .
@@ -157,6 +163,12 @@ Allow arbitrary recursive types during type-checking. By default,
only recursive types where the recursion goes through an object type
are supported.
.TP
+.B \-safe\-string
+Enforce the separation between types
+.BR string \ and\ bytes ,
+thereby making strings read-only. This will become the default in
+a future version of OCaml.
+.TP
.B \-short\-paths
When a type is visible under several module-paths, use the shortest
one when printing the type's name in inferred interfaces and error and
@@ -177,13 +189,20 @@ constructs). Programs compiled with
are therefore slightly faster, but unsafe: anything can happen if the program
accesses an array or string outside of its bounds.
.TP
+.B \-unsafe\-string
+Identify the types
+.BR string \ and\ bytes ,
+thereby making strings writable. For reasons of backward compatibility,
+this is the default setting for the moment, but this will change in a future
+version of OCaml.
+.TP
.B \-version
Print version string and exit.
.TP
.B \-vnum
Print short version number and exit.
.TP
-.BI \-w \ warning-list
+.BI \-w \ warning\-list
Enable or disable warnings according to the argument
.IR warning-list .
See
@@ -192,7 +211,7 @@ for the syntax of the
.I warning\-list
argument.
.TP
-.BI \-warn-error \ warning-list
+.BI \-warn\-error \ warning\-list
Mark as fatal the warnings described by the argument
.IR warning\-list .
Note that a warning is not triggered (and does not trigger an error) if
diff --git a/man/ocamlc.m b/man/ocamlc.m
index 1d3c56faa0..8661a76a76 100644
--- a/man/ocamlc.m
+++ b/man/ocamlc.m
@@ -396,6 +396,9 @@ bytecode executables produced with the option
.B ocamlc\ \-use\-runtime
.IR runtime-name .
.TP
+.B \-no-alias-deps
+Do not record dependencies for module aliases.
+.TP
.B \-no\-app\-funct
Deactivates the applicative behaviour of functors. With this option,
each functor application generates new types in its result and
@@ -446,6 +449,18 @@ packed object file produced. If the
.B \-output\-obj
option is given,
specify the name of the output file produced.
+This can also be used when compiling an interface or implementation
+file, without linking, in which case it sets the name of the cmi or
+cmo file, and also sets the module name to the file name up to the
+first dot.
+.TP
+.BI \-open \ module
+Opens the given module before processing the interface or
+implementation files. If several
+.B \-open
+options are given, they are processed in order, just as if
+the statements open! module1;; ... open! moduleN;; were added
+at the top of each file.
.TP
.B \-output\-obj
Cause the linker to produce a C object file instead of a bytecode
@@ -519,6 +534,12 @@ then the
.B d
suffix is supported and gives a debug version of the runtime.
.TP
+.B \-safe\-string
+Enforce the separation between types
+.BR string \ and\ bytes ,
+thereby making strings read-only. This will become the default in
+a future version of OCaml.
+.TP
.B \-short\-paths
When a type is visible under several module-paths, use the shortest
one when printing the type's name in inferred interfaces and error and
@@ -541,6 +562,13 @@ are therefore
slightly faster, but unsafe: anything can happen if the program
accesses an array or string outside of its bounds.
.TP
+.B \-unsafe\-string
+Identify the types
+.BR string \ and\ bytes ,
+thereby making strings writable. For reasons of backward compatibility,
+this is the default setting for the moment, but this will change in a future
+version of OCaml.
+.TP
.BI \-use\-runtime \ runtime\-name
Generate a bytecode executable file that can be executed on the custom
runtime system
@@ -773,7 +801,7 @@ mutually recursive types.
\ \ Unused constructor.
38
-\ \ Unused exception constructor.
+\ \ Unused extension constructor.
39
\ \ Unused rec flag.
@@ -875,7 +903,7 @@ Note: it is not recommended to use the
.B \-warn\-error
option in production code, because it will almost certainly prevent
compiling your program with later versions of OCaml when they add new
-warnings.
+warnings or modify existing warnings.
The default setting is
.B \-warn\-error\ -a (all warnings are non-fatal).
diff --git a/man/ocamlopt.m b/man/ocamlopt.m
index 766d2a4c6b..98ff86bf95 100644
--- a/man/ocamlopt.m
+++ b/man/ocamlopt.m
@@ -316,6 +316,9 @@ flag forces all
subsequent links of programs involving that library to link all the
modules contained in the library.
.TP
+.B \-no-alias-deps
+Do not record dependencies for module aliases.
+.TP
.B \-no\-app\-funct
Deactivates the applicative behaviour of functors. With this option,
each functor application generates new types in its result and
@@ -364,6 +367,18 @@ If the
option is given, specify the name of the output file produced. If the
.B \-shared
option is given, specify the name of plugin file produced.
+This can also be used when compiling an interface or implementation
+file, without linking, in which case it sets the name of the cmi or
+cmo file, and also sets the module name to the file name up to the
+first dot.
+.TP
+.BI \-open \ module
+Opens the given module before processing the interface or
+implementation files. If several
+.B \-open
+options are given, they are processed in order, just as if
+the statements open! module1;; ... open! moduleN;; were added
+at the top of each file.
.TP
.B \-output\-obj
Cause the linker to produce a C object file instead of an executable
@@ -475,6 +490,12 @@ code for the source file
is saved in the file
.IR x .s.
.TP
+.B \-safe\-string
+Enforce the separation between types
+.BR string \ and\ bytes ,
+thereby making strings read-only. This will become the default in
+a future version of OCaml.
+.TP
.B \-shared
Build a plugin (usually .cmxs) that can be dynamically loaded with
the
@@ -522,6 +543,13 @@ program or continue with an unspecified result instead of raising a
.B Division_by_zero
exception.
.TP
+.B \-unsafe\-string
+Identify the types
+.BR string \ and\ bytes ,
+thereby making strings writable. For reasons of backward compatibility,
+this is the default setting for the moment, but this will change in a future
+version of OCaml.
+.TP
.B \-v
Print the version number of the compiler and the location of the
standard library directory, then exit.
@@ -563,7 +591,7 @@ Note: it is not recommended to use the
.B \-warn\-error
option in production code, because it will almost certainly prevent
compiling your program with later versions of OCaml when they add new
-warnings.
+warnings or modify existing warnings.
The default setting is
.B \-warn\-error\ -a (all warnings are non-fatal).
diff --git a/ocamlbuild/Makefile b/ocamlbuild/Makefile
index 54d6283246..9f5dda3269 100644
--- a/ocamlbuild/Makefile
+++ b/ocamlbuild/Makefile
@@ -19,7 +19,7 @@ OCAMLOPT = $(OCAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib -I $(ROOTDIR)/stdlib
OCAMLDEP = $(OCAMLRUN) $(ROOTDIR)/tools/ocamldep
OCAMLLEX = $(OCAMLRUN) $(ROOTDIR)/boot/ocamllex
CP = cp
-COMPFLAGS= -warn-error A -w L -w R -w Z -I ../otherlibs/$(UNIXLIB)
+COMPFLAGS= -warn-error A -w L -w R -w Z -I ../otherlibs/$(UNIXLIB) -safe-string
LINKFLAGS= -I ../otherlibs/$(UNIXLIB)
PACK_CMO=\
@@ -73,6 +73,7 @@ EXTRA_CMO=\
PACK_CMX=$(PACK_CMO:.cmo=.cmx)
EXTRA_CMX=$(EXTRA_CMO:.cmo=.cmx)
+EXTRA_CMI=$(EXTRA_CMO:.cmo=.cmi)
INSTALL_LIB=\
ocamlbuildlib.cma \
@@ -197,6 +198,10 @@ clean::
depend: beforedepend
$(OCAMLDEP) *.mli *.ml > .depend
+$(EXTRA_CMI): ocamlbuild_pack.cmi
+$(EXTRA_CMO): ocamlbuild_pack.cmo ocamlbuild_pack.cmi
+$(EXTRA_CMX): ocamlbuild_pack.cmx ocamlbuild_pack.cmi
+
include .depend
.PHONY: all allopt clean beforedepend
diff --git a/ocamlbuild/Makefile.noboot b/ocamlbuild/Makefile.noboot
index de914e15ec..313e56891c 100644
--- a/ocamlbuild/Makefile.noboot
+++ b/ocamlbuild/Makefile.noboot
@@ -56,7 +56,7 @@ INCLUDES_NODEP= -I $(OCAMLSRCDIR)/stdlib \
INCLUDES=$(INCLUDES_DEP) $(INCLUDES_NODEP)
-COMPFLAGS=$(INCLUDES) -warn-error A
+COMPFLAGS=$(INCLUDES) -warn-error A -safe-string
LINKFLAGS=$(INCLUDES)
CMOFILES_PACK= \
diff --git a/ocamlbuild/display.ml b/ocamlbuild/display.ml
index 725d351bb6..2e0b1e39ea 100644
--- a/ocamlbuild/display.ml
+++ b/ocamlbuild/display.ml
@@ -51,7 +51,7 @@ type sophisticated_display = {
ds_columns : int; (** Number of columns in dssplay *)
mutable ds_jobs : int; (** Number of jobs launched or cached *)
mutable ds_jobs_cached : int; (** Number of jobs cached *)
- ds_tagline : string; (** Current tagline *)
+ ds_tagline : bytes; (** Current tagline *)
mutable ds_seen_tags : Tags.t; (** Tags that we have encountered *)
ds_pathname_length : int; (** How much space for displaying pathnames ? *)
ds_tld : tagline_description; (** Description for the tagline *)
@@ -105,7 +105,7 @@ let uncached = " ";;
let cache_chars = 1;;
(* ***)
(*** create_tagline *)
-let create_tagline description = String.make (List.length description) '-';;
+let create_tagline description = Bytes.make (List.length description) '-';;
(* ***)
(*** create *)
let create
@@ -184,7 +184,7 @@ let print_shortened_pathname length oc u =
let n = String.length dots in
let k = length - n in
output_string oc dots;
- output oc u (m - k) k;
+ output_substring oc u (m - k) k;
end
(* ***)
(*** Layout
@@ -216,7 +216,7 @@ let redraw_sophisticated ds =
ds.ds_jobs_cached
(print_shortened_pathname ds.ds_pathname_length) ds.ds_last_target
(if ds.ds_last_cached then cached else uncached)
- ds.ds_tagline
+ (Bytes.to_string ds.ds_tagline)
ticker;
fp oc "%a%!" ANSI.clear_to_eol ()
;;
@@ -292,17 +292,17 @@ let update_tagline_from_tags ds =
let tags = ds.ds_last_tags in
let rec loop i = function
| [] ->
- for j = i to String.length tagline - 1 do
- tagline.[j] <- '-'
+ for j = i to Bytes.length tagline - 1 do
+ Bytes.set tagline j '-'
done
| (tag, c) :: rest ->
if Tags.mem tag tags then
- tagline.[i] <- Char.uppercase c
+ Bytes.set tagline i (Char.uppercase c)
else
if Tags.mem tag ds.ds_seen_tags then
- tagline.[i] <- Char.lowercase c
+ Bytes.set tagline i (Char.lowercase c)
else
- tagline.[i] <- '-';
+ Bytes.set tagline i '-';
loop (i + 1) rest
in
loop 0 ds.ds_tld;
diff --git a/ocamlbuild/main.ml b/ocamlbuild/main.ml
index 5f86f7932a..7413a7a7f6 100644
--- a/ocamlbuild/main.ml
+++ b/ocamlbuild/main.ml
@@ -56,9 +56,12 @@ let show_documentation () =
this means that even if they were not part of any flag declaration,
they should be marked as useful, to avoid the "unused tag" warning. *)
let builtin_useful_tags =
- Tags.of_list
- ["include"; "traverse"; "not_hygienic";
- "pack"; "ocamlmklib"; "native"; "thread"; "nopervasives"]
+ Tags.of_list [
+ "include"; "traverse"; "not_hygienic";
+ "pack"; "ocamlmklib"; "native"; "thread";
+ "nopervasives"; "use_menhir"; "ocamldep";
+ "thread";
+ ]
;;
let proceed () =
@@ -110,7 +113,7 @@ let proceed () =
let entry_include_dirs = ref [] in
let entry =
Slurp.filter
- begin fun path name _ ->
+ begin fun path name () ->
let dir =
if path = Filename.current_dir_name then
None
@@ -118,8 +121,21 @@ let proceed () =
Some path
in
let path_name = path/name in
- if name = "_tags" then
- ignore (Configuration.parse_file ?dir path_name);
+
+ if name = "_tags" then begin
+ let tags_path =
+ (* PR#6482: remember that this code is run lazily by the Slurp command,
+ and may run only after the working directory has been changed.
+
+ On the other hand, always using the absolute path makes
+ error messages longer and more frigthening in case of
+ syntax error in the _tags file. So we use the absolute
+ path only when necessary -- the working directory has
+ changed. *)
+ if Sys.getcwd () = Pathname.pwd then path_name
+ else Pathname.pwd / path_name in
+ ignore (Configuration.parse_file ?dir tags_path);
+ end;
(List.mem name ["_oasis"] || (String.length name > 0 && name.[0] <> '_'))
&& (name <> !Options.build_dir && not (List.mem name !Options.exclude_dirs))
@@ -148,10 +164,9 @@ let proceed () =
let tags = tags_of_pathname (path/name) in
not (Tags.mem "not_hygienic" tags) && not (Tags.mem "precious" tags)
end entry in
+ Slurp.force hygiene_entry;
if !Options.hygiene && not first_run_for_plugin then
- Fda.inspect hygiene_entry
- else
- Slurp.force hygiene_entry;
+ Fda.inspect hygiene_entry;
let entry = hygiene_entry in
Hooks.call_hook Hooks.After_hygiene;
Options.include_dirs := Pathname.current_dir_name :: List.rev !entry_include_dirs;
@@ -282,8 +297,10 @@ let main () =
Log.finish ~how:`Quiet ();
Pervasives.exit rc
| Solver.Failed backtrace ->
- Log.raw_dprintf (-1) "@[<v0>@[<2>Solver failed:@ %a@]@\n@[<v2>Backtrace:%a@]@]@."
- Report.print_backtrace_analyze backtrace Report.print_backtrace backtrace;
+ Log.raw_dprintf (-1) "@[<v0>@[<2>Solver failed:@ %a@]@."
+ Report.print_backtrace_analyze backtrace;
+ Log.raw_dprintf 1 "@[<v2>Backtrace:%a@]@]@."
+ Report.print_backtrace backtrace;
exit rc_solver_failed
| Failure s ->
Log.eprintf "Failure:@ %s." s;
diff --git a/ocamlbuild/my_std.ml b/ocamlbuild/my_std.ml
index e0d2c8a9ca..c283987cc2 100644
--- a/ocamlbuild/my_std.ml
+++ b/ocamlbuild/my_std.ml
@@ -180,14 +180,7 @@ module String = struct
in loop s 0
let tr patt subst text =
- let len = length text in
- let text = copy text in
- let rec loop pos =
- if pos < len then begin
- (if text.[pos] = patt then text.[pos] <- subst);
- loop (pos + 1)
- end
- in loop 0; text
+ String.map (fun c -> if c = patt then subst else c) text
(*** is_prefix : is u a prefix of v ? *)
let is_prefix u v =
@@ -211,23 +204,23 @@ module String = struct
let rev s =
let sl = String.length s in
- let s' = String.create sl in
+ let s' = Bytes.create sl in
for i = 0 to sl - 1 do
- s'.[i] <- s.[sl - i - 1]
+ Bytes.set s' i s.[sl - i - 1]
done;
- s';;
+ Bytes.to_string s';;
let implode l =
match l with
| [] -> ""
| cs ->
- let r = create (List.length cs) in
+ let r = Bytes.create (List.length cs) in
let pos = ref 0 in
List.iter begin fun c ->
- unsafe_set r !pos c;
+ Bytes.unsafe_set r !pos c;
incr pos
end cs;
- r
+ Bytes.to_string r
let explode s =
let sl = String.length s in
@@ -307,16 +300,14 @@ let with_output_file ?(bin=false) x f =
let read_file x =
with_input_file ~bin:true x begin fun ic ->
let len = in_channel_length ic in
- let buf = String.create len in
- let () = really_input ic buf 0 len in
- buf
+ really_input_string ic len
end
let copy_chan ic oc =
let m = in_channel_length ic in
let m = (m lsr 12) lsl 12 in
let m = max 16384 (min Sys.max_string_length m) in
- let buf = String.create m in
+ let buf = Bytes.create m in
let rec loop () =
let len = input ic buf 0 m in
if len > 0 then begin
diff --git a/ocamlbuild/my_unix.ml b/ocamlbuild/my_unix.ml
index 43692d3219..fa1c5d45f4 100644
--- a/ocamlbuild/my_unix.ml
+++ b/ocamlbuild/my_unix.ml
@@ -127,13 +127,13 @@ let execute_many ?max_jobs = implem.execute_many ?max_jobs
let run_and_read cmd =
let bufsiz = 2048 in
- let buf = String.create bufsiz in
+ let buf = Bytes.create bufsiz in
let totalbuf = Buffer.create 4096 in
implem.run_and_open cmd begin fun ic ->
let rec loop pos =
let len = input ic buf 0 bufsiz in
if len > 0 then begin
- Buffer.add_substring totalbuf buf 0 len;
+ Buffer.add_subbytes totalbuf buf 0 len;
loop (pos + len)
end
in loop 0; Buffer.contents totalbuf
diff --git a/ocamlbuild/ocaml_specific.ml b/ocamlbuild/ocaml_specific.ml
index 1b41c0842b..43605d361e 100644
--- a/ocamlbuild/ocaml_specific.ml
+++ b/ocamlbuild/ocaml_specific.ml
@@ -665,6 +665,10 @@ flag ["ocaml"; "link"; "byte"; "output_obj"] (A"-output-obj");;
flag ["ocaml"; "dtypes"; "compile"] (A "-dtypes");;
flag ["ocaml"; "annot"; "compile"] (A "-annot");;
flag ["ocaml"; "bin_annot"; "compile"] (A "-bin-annot");;
+flag ["ocaml"; "safe_string"; "compile"] (A "-safe-string");;
+flag ["ocaml"; "safe_string"; "infer_interface"] (A "-safe-string");;
+flag ["ocaml"; "unsafe_string"; "compile"] (A "-unsafe-string");;
+flag ["ocaml"; "unsafe_string"; "infer_interface"] (A "-unsafe-string");;
flag ["ocaml"; "short_paths"; "compile"] (A "-short-paths");;
flag ["ocaml"; "short_paths"; "infer_interface"] (A "-short-paths");;
flag ["ocaml"; "rectypes"; "compile"] (A "-rectypes");;
@@ -678,6 +682,7 @@ flag ["ocaml"; "link"; "profile"; "native"] (A "-p");;
flag ["ocaml"; "link"; "program"; "custom"; "byte"] (A "-custom");;
flag ["ocaml"; "link"; "library"; "custom"; "byte"] (A "-custom");;
flag ["ocaml"; "compile"; "profile"; "native"] (A "-p");;
+flag ["ocaml"; "compile"; "no_alias_deps";] (A "-no-alias-deps");;
(* threads, with or without findlib *)
flag ["ocaml"; "compile"; "thread"] (A "-thread");;
diff --git a/ocamlbuild/ocamlbuild_executor.ml b/ocamlbuild/ocamlbuild_executor.ml
index 53fcad1201..298f9b4dd7 100644
--- a/ocamlbuild/ocamlbuild_executor.ml
+++ b/ocamlbuild/ocamlbuild_executor.ml
@@ -59,22 +59,19 @@ let output_lines prefix oc buffer =
let m = String.length u in
let output_line i j =
output_string oc prefix;
- output oc u i (j - i);
+ output_substring oc u i (j - i);
output_char oc '\n'
in
let rec loop i =
- if i = m then
- ()
+ if i < m then
+ let j =
+ try String.index_from u i '\n'
+ with Not_found -> m
+ in
+ output_line i j;
+ loop (j + 1)
else
- begin
- try
- let j = String.index_from u i '\n' in
- output_line i j;
- loop (j + 1)
- with
- | Not_found ->
- output_line i m
- end
+ ()
in
loop 0
;;
@@ -190,7 +187,7 @@ let execute
(* ***)
(*** do_read *)
let do_read =
- let u = String.create 4096 in
+ let u = Bytes.create 4096 in
fun ?(loop=false) fd job ->
(*if job.job_dying then
()
@@ -199,9 +196,13 @@ let execute
let rec iteration () =
let m =
try
- read fd u 0 (String.length u)
+ read fd u 0 (Bytes.length u)
with
- | Unix.Unix_error(_,_,_) -> 0
+ | Unix.Unix_error(e,_,_) ->
+ let msg = error_message e in
+ display (fun oc -> fp oc
+ "Error while reading stdout/stderr: %s\n" msg);
+ 0
in
if m = 0 then
if job.job_dying then
@@ -210,7 +211,7 @@ let execute
terminate job
else
begin
- Buffer.add_substring job.job_buffer u 0 m;
+ Buffer.add_subbytes job.job_buffer u 0 m;
if loop then
iteration ()
else
@@ -237,6 +238,11 @@ let execute
(*display begin fun oc -> fp oc "Terminating job %a\n%!" print_job_id job.job_id; end;*)
decr jobs_active;
+
+ (* PR#5371: we would get EAGAIN below otherwise *)
+ clear_nonblock (doi job.job_stdout);
+ clear_nonblock (doi job.job_stderr);
+
do_read ~loop:true (doi job.job_stdout) job;
do_read ~loop:true (doi job.job_stderr) job;
outputs := FDM.remove (doi job.job_stdout) (FDM.remove (doi job.job_stderr) !outputs);
diff --git a/ocamlbuild/options.ml b/ocamlbuild/options.ml
index 78cee63734..68c0ac85db 100644
--- a/ocamlbuild/options.ml
+++ b/ocamlbuild/options.ml
@@ -38,7 +38,7 @@ let make_links = ref true
let nostdlib = ref false
let use_menhir = ref false
let catch_errors = ref true
-let use_ocamlfind = ref true
+let use_ocamlfind = ref false
(* Currently only ocamlfind and menhir is defined as no-core tool,
perhaps later we need something better *)
diff --git a/ocamlbuild/testsuite/internal.ml b/ocamlbuild/testsuite/internal.ml
index 5d3c288400..2a12070f95 100644
--- a/ocamlbuild/testsuite/internal.ml
+++ b/ocamlbuild/testsuite/internal.ml
@@ -251,4 +251,17 @@ let () = test "PluginTagsWarning"
in absence of plugin file \"myocamlbuild.ml\""
~targets:("main.ml", []) ();;
+let () = test "TagsInNonHygienic"
+ ~description:"Regression test for PR#6482, where a _tags \
+ in a non-traversed directory would cause \
+ ocamlbuild to abort"
+ ~options:[`no_ocamlfind]
+ ~tree:[
+ T.f "main.ml" ~content:"";
+ T.d "deps" [T.f "_tags" ~content:""];
+ T.f "_tags" ~content:"<deps>: not_hygienic\n";
+ ]
+ ~matching:[M.f "main.byte"]
+ ~targets:("main.byte",[]) ();;
+
run ~root:"_test_internal";;
diff --git a/ocamldoc/.depend b/ocamldoc/.depend
index 38e932e35b..c2965f6a30 100644
--- a/ocamldoc/.depend
+++ b/ocamldoc/.depend
@@ -32,16 +32,16 @@ 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_name.cmi odoc_module.cmo odoc_messages.cmo \
- odoc_global.cmi 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_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_name.cmx odoc_module.cmx odoc_messages.cmx \
- odoc_global.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_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_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 \
@@ -62,12 +62,12 @@ 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_exception.cmo \
- odoc_class.cmo odoc_cross.cmi
+ 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_exception.cmx \
- odoc_class.cmx odoc_cross.cmi
+ odoc_misc.cmx odoc_messages.cmx odoc_global.cmx odoc_extension.cmx \
+ odoc_exception.cmx odoc_class.cmx odoc_cross.cmi
odoc_dag2html.cmo : odoc_info.cmi odoc_dag2html.cmi
odoc_dag2html.cmx : odoc_info.cmx odoc_dag2html.cmi
odoc_dep.cmo : ../parsing/parsetree.cmi odoc_type.cmo odoc_print.cmi \
@@ -84,6 +84,10 @@ odoc_env.cmx : ../typing/types.cmx ../typing/printtyp.cmx \
../typing/btype.cmx odoc_env.cmi
odoc_exception.cmo : ../typing/types.cmi odoc_types.cmi odoc_name.cmi
odoc_exception.cmx : ../typing/types.cmx odoc_types.cmx odoc_name.cmx
+odoc_extension.cmo : ../typing/types.cmi odoc_types.cmi odoc_name.cmi \
+ ../parsing/asttypes.cmi
+odoc_extension.cmx : ../typing/types.cmx odoc_types.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 \
@@ -99,15 +103,15 @@ odoc_html.cmx : odoc_text.cmx odoc_ocamlhtml.cmx odoc_messages.cmx \
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_exception.cmo odoc_dep.cmo \
- odoc_config.cmi odoc_comments.cmi odoc_class.cmo odoc_analyse.cmi \
- ../parsing/location.cmi odoc_info.cmi
+ 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_exception.cmx odoc_dep.cmx \
- odoc_config.cmx odoc_comments.cmx odoc_class.cmx odoc_analyse.cmx \
- ../parsing/location.cmx odoc_info.cmi
+ 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_inherit.cmo :
odoc_inherit.cmx :
odoc_latex.cmo : odoc_to_text.cmo odoc_messages.cmo odoc_latex_style.cmo \
@@ -126,10 +130,12 @@ 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_name.cmi odoc_module.cmo odoc_messages.cmo \
- odoc_global.cmi odoc_exception.cmo odoc_class.cmo odoc_merge.cmi
+ 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_name.cmx odoc_module.cmx odoc_messages.cmx \
- odoc_global.cmx odoc_exception.cmx odoc_class.cmx odoc_merge.cmi
+ odoc_global.cmx odoc_extension.cmx odoc_exception.cmx odoc_class.cmx \
+ odoc_merge.cmi
odoc_messages.cmo : ../utils/config.cmi
odoc_messages.cmx : ../utils/config.cmx
odoc_misc.cmo : ../typing/types.cmi ../typing/predef.cmi ../typing/path.cmi \
@@ -139,9 +145,11 @@ 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_module.cmo : ../typing/types.cmi odoc_value.cmo odoc_types.cmi \
- odoc_type.cmo odoc_name.cmi odoc_exception.cmo odoc_class.cmo
+ odoc_type.cmo odoc_name.cmi odoc_extension.cmo odoc_exception.cmo \
+ odoc_class.cmo
odoc_module.cmx : ../typing/types.cmx odoc_value.cmx odoc_types.cmx \
- odoc_type.cmx odoc_name.cmx odoc_exception.cmx odoc_class.cmx
+ odoc_type.cmx odoc_name.cmx odoc_extension.cmx odoc_exception.cmx \
+ odoc_class.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 \
@@ -157,38 +165,38 @@ odoc_print.cmo : ../typing/types.cmi ../typing/printtyp.cmi \
odoc_print.cmx : ../typing/types.cmx ../typing/printtyp.cmx \
../utils/misc.cmx odoc_print.cmi
odoc_scan.cmo : odoc_value.cmo odoc_types.cmi odoc_type.cmo odoc_module.cmo \
- odoc_exception.cmo odoc_class.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_exception.cmx odoc_class.cmx
+ odoc_extension.cmx odoc_exception.cmx odoc_class.cmx
odoc_search.cmo : odoc_value.cmo odoc_types.cmi odoc_type.cmo \
- odoc_parameter.cmo odoc_name.cmi odoc_module.cmo odoc_exception.cmo \
- odoc_class.cmo odoc_search.cmi
+ odoc_parameter.cmo odoc_name.cmi 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_parameter.cmx odoc_name.cmx odoc_module.cmx odoc_exception.cmx \
- odoc_class.cmx odoc_search.cmi
+ odoc_parameter.cmx odoc_name.cmx odoc_module.cmx odoc_extension.cmx \
+ odoc_exception.cmx odoc_class.cmx odoc_search.cmi
odoc_see_lexer.cmo : odoc_parser.cmi
odoc_see_lexer.cmx : odoc_parser.cmx
odoc_sig.cmo : ../typing/types.cmi ../typing/typedtree.cmi \
../typing/path.cmi ../parsing/parsetree.cmi odoc_value.cmo odoc_types.cmi \
odoc_type.cmo odoc_parameter.cmo odoc_name.cmi odoc_module.cmo \
odoc_misc.cmi odoc_messages.cmo odoc_merge.cmi odoc_global.cmi \
- odoc_exception.cmo odoc_env.cmi odoc_class.cmo ../utils/misc.cmi \
- ../parsing/location.cmi ../typing/ident.cmi ../typing/btype.cmi \
- ../parsing/asttypes.cmi odoc_sig.cmi
+ odoc_extension.cmo odoc_exception.cmo odoc_env.cmi odoc_class.cmo \
+ ../utils/misc.cmi ../parsing/location.cmi ../typing/ident.cmi \
+ ../typing/btype.cmi ../parsing/asttypes.cmi odoc_sig.cmi
odoc_sig.cmx : ../typing/types.cmx ../typing/typedtree.cmx \
../typing/path.cmx ../parsing/parsetree.cmi odoc_value.cmx odoc_types.cmx \
odoc_type.cmx odoc_parameter.cmx odoc_name.cmx odoc_module.cmx \
odoc_misc.cmx odoc_messages.cmx odoc_merge.cmx odoc_global.cmx \
- odoc_exception.cmx odoc_env.cmx odoc_class.cmx ../utils/misc.cmx \
- ../parsing/location.cmx ../typing/ident.cmx ../typing/btype.cmx \
- ../parsing/asttypes.cmi odoc_sig.cmi
+ odoc_extension.cmx odoc_exception.cmx odoc_env.cmx odoc_class.cmx \
+ ../utils/misc.cmx ../parsing/location.cmx ../typing/ident.cmx \
+ ../typing/btype.cmx ../parsing/asttypes.cmi odoc_sig.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_exception.cmo odoc_class.cmo \
+ 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_exception.cmx odoc_class.cmx \
+ odoc_messages.cmx odoc_extension.cmx odoc_exception.cmx odoc_class.cmx \
../parsing/asttypes.cmi odoc_str.cmi
odoc_test.cmo : odoc_info.cmi odoc_gen.cmi odoc_args.cmi
odoc_test.cmx : odoc_info.cmx odoc_gen.cmx odoc_args.cmx
@@ -219,8 +227,7 @@ odoc_value.cmx : ../typing/types.cmx ../typing/printtyp.cmx odoc_types.cmx \
odoc_analyse.cmi : odoc_module.cmo odoc_global.cmi
odoc_args.cmi : odoc_gen.cmi
odoc_ast.cmi : ../typing/types.cmi ../typing/typedtree.cmi \
- ../typing/path.cmi ../parsing/parsetree.cmi odoc_sig.cmi odoc_name.cmi \
- odoc_module.cmo
+ ../parsing/parsetree.cmi odoc_sig.cmi odoc_name.cmi odoc_module.cmo
odoc_comments.cmi : odoc_types.cmi odoc_module.cmo
odoc_comments_global.cmi :
odoc_config.cmi :
@@ -232,7 +239,8 @@ odoc_gen.cmi : odoc_texi.cmo odoc_module.cmo odoc_man.cmo odoc_latex.cmo \
odoc_global.cmi : odoc_types.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_exception.cmo odoc_class.cmo ../parsing/location.cmi
+ odoc_global.cmi odoc_extension.cmo odoc_exception.cmo odoc_class.cmo \
+ ../parsing/location.cmi
odoc_merge.cmi : odoc_types.cmi odoc_module.cmo
odoc_misc.cmi : ../typing/types.cmi odoc_types.cmi ../parsing/longident.cmi
odoc_name.cmi : ../typing/path.cmi ../parsing/longident.cmi \
@@ -240,11 +248,11 @@ odoc_name.cmi : ../typing/path.cmi ../parsing/longident.cmi \
odoc_parser.cmi : odoc_types.cmi
odoc_print.cmi : ../typing/types.cmi
odoc_search.cmi : odoc_value.cmo odoc_types.cmi odoc_type.cmo \
- odoc_module.cmo odoc_exception.cmo odoc_class.cmo
+ odoc_module.cmo odoc_extension.cmo odoc_exception.cmo odoc_class.cmo
odoc_sig.cmi : ../typing/types.cmi ../parsing/parsetree.cmi odoc_types.cmi \
odoc_type.cmo odoc_name.cmi odoc_module.cmo odoc_env.cmi odoc_class.cmo
odoc_str.cmi : ../typing/types.cmi odoc_value.cmo odoc_type.cmo \
- odoc_exception.cmo odoc_class.cmo
+ odoc_extension.cmo odoc_exception.cmo odoc_class.cmo
odoc_text.cmi : odoc_types.cmi
odoc_text_parser.cmi : odoc_types.cmi
odoc_types.cmi : ../parsing/location.cmi
diff --git a/ocamldoc/Makefile b/ocamldoc/Makefile
index f5e47a59bd..564a26bfd9 100644
--- a/ocamldoc/Makefile
+++ b/ocamldoc/Makefile
@@ -76,7 +76,7 @@ INCLUDES_NODEP= -I $(OCAMLSRCDIR)/stdlib \
INCLUDES=$(INCLUDES_DEP) $(INCLUDES_NODEP)
-COMPFLAGS=$(INCLUDES) -warn-error A
+COMPFLAGS=$(INCLUDES) -warn-error A -safe-string
LINKFLAGS=$(INCLUDES) -nostdlib
CMOFILES= odoc_config.cmo \
@@ -91,6 +91,7 @@ CMOFILES= odoc_config.cmo \
odoc_parameter.cmo\
odoc_value.cmo\
odoc_type.cmo\
+ odoc_extension.cmo\
odoc_exception.cmo\
odoc_class.cmo\
odoc_module.cmo\
diff --git a/ocamldoc/Makefile.nt b/ocamldoc/Makefile.nt
index 158fa7db34..591c194602 100644
--- a/ocamldoc/Makefile.nt
+++ b/ocamldoc/Makefile.nt
@@ -79,6 +79,7 @@ CMOFILES= odoc_config.cmo \
odoc_parameter.cmo\
odoc_value.cmo\
odoc_type.cmo\
+ odoc_extension.cmo\
odoc_exception.cmo\
odoc_class.cmo\
odoc_module.cmo\
diff --git a/ocamldoc/generators/odoc_todo.ml b/ocamldoc/generators/odoc_todo.ml
index 31545feef8..9dbf9f3759 100644
--- a/ocamldoc/generators/odoc_todo.ml
+++ b/ocamldoc/generators/odoc_todo.ml
@@ -18,6 +18,7 @@ module Naming = Odoc_html.Naming
open Odoc_info.Value
open Odoc_info.Module
open Odoc_info.Type
+open Odoc_info.Extension
open Odoc_info.Exception
open Odoc_info.Class
@@ -115,6 +116,12 @@ struct
(Odoc_html.Naming.complete_type_target t)
t.ty_info
+ method scan_extension_constructor x =
+ self#gen_if_tag
+ x.xt_name
+ (Odoc_html.Naming.complete_extension_target x)
+ x.xt_type_extension.te_info
+
method scan_exception e =
self#gen_if_tag
e.ex_name
@@ -144,6 +151,7 @@ struct
| Odoc_module.Element_class c -> self#scan_class c
| Odoc_module.Element_class_type ct -> self#scan_class_type ct
| Odoc_module.Element_value v -> self#scan_value v
+ | Odoc_module.Element_type_extension te -> self#scan_type_extension te
| Odoc_module.Element_exception e -> self#scan_exception e
| Odoc_module.Element_type t -> self#scan_type t
| Odoc_module.Element_module_comment t -> self#scan_module_comment t
diff --git a/ocamldoc/odoc_analyse.ml b/ocamldoc/odoc_analyse.ml
index 98f73617df..31328838f4 100644
--- a/ocamldoc/odoc_analyse.ml
+++ b/ocamldoc/odoc_analyse.ml
@@ -33,10 +33,13 @@ let init_path () =
(** Return the initial environment in which compilation proceeds. *)
let initial_env () =
+ let initial =
+ if !Clflags.unsafe_string then Env.initial_unsafe_string
+ else Env.initial_safe_string
+ in
try
- if !Clflags.nopervasives
- then Env.initial
- else Env.open_pers_signature "Pervasives" Env.initial
+ if !Clflags.nopervasives then initial else
+ Env.open_pers_signature "Pervasives" initial
with Not_found ->
fatal_error "cannot open pervasives.cmi"
@@ -53,6 +56,9 @@ let (++) x f = f x
(** Analysis of an implementation file. Returns (Some typedtree) if
no error occured, else None and an error message is printed.*)
+
+let tool_name = "ocamldoc"
+
let process_implementation_file ppf sourcefile =
init_path ();
let prefixname = Filename.chop_extension sourcefile in
@@ -61,7 +67,10 @@ let process_implementation_file ppf sourcefile =
let inputfile = preprocess sourcefile in
let env = initial_env () in
try
- let parsetree = Pparse.file Format.err_formatter inputfile Parse.implementation ast_impl_magic_number in
+ let parsetree =
+ Pparse.file ~tool_name Format.err_formatter inputfile
+ Parse.implementation ast_impl_magic_number
+ in
let typedtree =
Typemod.type_implementation
sourcefile prefixname modulename env parsetree
@@ -89,8 +98,11 @@ let process_interface_file ppf sourcefile =
let modulename = String.capitalize(Filename.basename prefixname) in
Env.set_unit_name modulename;
let inputfile = preprocess sourcefile in
- let ast = Pparse.file Format.err_formatter inputfile Parse.interface ast_intf_magic_number in
- let sg = Typemod.transl_signature (initial_env()) ast in
+ let ast =
+ Pparse.file ~tool_name Format.err_formatter inputfile
+ Parse.interface ast_intf_magic_number
+ in
+ let sg = Typemod.type_interface (initial_env()) ast in
Warnings.check_fatal ();
(ast, sg, inputfile)
@@ -318,6 +330,7 @@ let rec remove_module_elements_between_stop keep eles =
else
f keep q
| Odoc_module.Element_value _
+ | Odoc_module.Element_type_extension _
| Odoc_module.Element_exception _
| Odoc_module.Element_type _ ->
if keep then
diff --git a/ocamldoc/odoc_ast.ml b/ocamldoc/odoc_ast.ml
index 3e0cc83b6e..358a71a51c 100644
--- a/ocamldoc/odoc_ast.ml
+++ b/ocamldoc/odoc_ast.ml
@@ -25,6 +25,7 @@ module Name = Odoc_name
open Odoc_parameter
open Odoc_value
open Odoc_type
+open Odoc_extension
open Odoc_exception
open Odoc_class
open Odoc_module
@@ -48,8 +49,8 @@ module Typedtree_search =
| T of string
| C of string
| CT of string
+ | X of string
| E of string
- | ER of string
| P of string
| IM of string
@@ -75,10 +76,13 @@ module Typedtree_search =
mods
| Typedtree.Tstr_modtype mtd ->
Hashtbl.add table (MT (Name.from_ident mtd.mtd_id)) tt
- | Typedtree.Tstr_exception decl ->
- Hashtbl.add table (E (Name.from_ident decl.cd_id)) tt
- | Typedtree.Tstr_exn_rebind er ->
- Hashtbl.add table (ER (Name.from_ident er.exrb_id)) tt
+ | Typedtree.Tstr_typext te -> begin
+ match te.tyext_constructors with
+ [] -> assert false
+ | 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
| Typedtree.Tstr_type ident_type_decl_list ->
List.iter
(fun td ->
@@ -129,14 +133,14 @@ module Typedtree_search =
| (Typedtree.Tstr_modtype mtd) -> mtd
| _ -> assert false
- let search_exception table name =
- match Hashtbl.find table (E name) with
- | (Typedtree.Tstr_exception decl) -> decl
+ let search_extension table name =
+ match Hashtbl.find table (X name) with
+ | (Typedtree.Tstr_typext tyext) -> tyext
| _ -> assert false
- let search_exception_rebind table name =
- match Hashtbl.find table (ER name) with
- | (Typedtree.Tstr_exn_rebind er) -> er.exrb_path
+ let search_exception table name =
+ match Hashtbl.find table (E name) with
+ | (Typedtree.Tstr_exception ext) -> ext
| _ -> assert false
let search_type_declaration table name =
@@ -679,6 +683,9 @@ module Analyser =
| (Parsetree.Pcf_initializer exp) ->
iter acc_inher acc_fields exp.Parsetree.pexp_loc.Location.loc_end.Lexing.pos_cnum q
+ | Parsetree.Pcf_attribute _ ->
+ iter acc_inher acc_fields loc.Location.loc_end.Lexing.pos_cnum q
+
| Parsetree.Pcf_extension _ -> assert false
in
iter [] [] last_pos (p_cls.Parsetree.pcstr_fields)
@@ -979,9 +986,17 @@ module Analyser =
and n2 = Ident.name ident in
n1 = n2
| _ -> false)
+ | Element_type_extension te ->
+ let l =
+ filter_extension_constructors_with_module_type_constraint
+ te.te_constructors lsig
+ in
+ te.te_constructors <- l;
+ if l <> [] then (fun _ -> true)
+ else (fun _ -> false)
| Element_exception e ->
(function
- Types.Sig_exception (ident,_) ->
+ Types.Sig_typext (ident,_,_) ->
let n1 = Name.simple e.ex_name
and n2 = Ident.name ident in
n1 = n2
@@ -1007,6 +1022,19 @@ module Analyser =
in
List.filter pred l
+ and filter_extension_constructors_with_module_type_constraint l lsig =
+ let pred xt =
+ List.exists
+ (function
+ Types.Sig_typext (ident, _, _) ->
+ let n1 = Name.simple xt.xt_name
+ and n2 = Ident.name ident in
+ n1 = n2
+ | _ -> false)
+ lsig
+ in
+ List.filter pred l
+
(** Analysis of a parse tree structure with a typed tree, to return module elements.*)
let rec analyse_structure env current_module_name last_pos pos_limit parsetree typedtree =
print_DEBUG "Odoc_ast:analyse_struture";
@@ -1178,10 +1206,7 @@ module Analyser =
| td :: _ -> td.Parsetree.ptype_loc.Location.loc_start.Lexing.pos_cnum
in
let (maybe_more, name_comment_list) =
- Sig.name_comment_from_type_kind
- loc_end
- pos_limit2
- type_decl.Parsetree.ptype_kind
+ Sig.name_comment_from_type_decl loc_end pos_limit2 type_decl
in
let tt_type_decl =
try Typedtree_search.search_type_declaration table name
@@ -1215,7 +1240,8 @@ module Analyser =
ty_manifest =
(match tt_type_decl.Types.type_manifest with
None -> None
- | Some t -> Some (Odoc_env.subst_type new_env t));
+ | Some t ->
+ Some (Sig.manifest_structure new_env name_comment_list t));
ty_loc = { loc_impl = Some loc ; loc_inter = None } ;
ty_code =
(
@@ -1238,61 +1264,152 @@ module Analyser =
let (maybe_more, eles) = f ~first: true 0 loc.Location.loc_start.Lexing.pos_cnum name_typedecl_list in
(maybe_more, new_env, eles)
- | Parsetree.Pstr_exception excep_decl ->
- let name = excep_decl.Parsetree.pcd_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 *)
- let tt_excep_decl =
- try Typedtree_search.search_exception table name.txt
- with Not_found ->
- raise (Failure (Odoc_messages.exception_not_found_in_typedtree complete_name))
+ | Parsetree.Pstr_typext tyext ->
+ (* we get the extension declaration in the typed tree *)
+ let tt_tyext =
+ match tyext.Parsetree.ptyext_constructors with
+ [] -> assert false
+ | ext :: _ ->
+ try
+ Typedtree_search.search_extension table ext.Parsetree.pext_name.txt
+ with Not_found ->
+ raise (Failure
+ (Odoc_messages.extension_not_found_in_typedtree
+ (Name.concat current_module_name ext.Parsetree.pext_name.txt)))
+ in
+ let new_env =
+ List.fold_left
+ (fun acc_env -> fun {Parsetree.pext_name = { txt = name }} ->
+ let complete_name = Name.concat current_module_name name in
+ Odoc_env.add_extension acc_env complete_name
+ )
+ env
+ tyext.Parsetree.ptyext_constructors
in
- let new_env = Odoc_env.add_exception env complete_name in
let loc_start = loc.Location.loc_start.Lexing.pos_cnum in
let loc_end = loc.Location.loc_end.Lexing.pos_cnum in
- let new_ex =
+ let new_te =
{
- ex_name = complete_name ;
- ex_info = comment_opt ;
- ex_args = List.map (fun ctyp ->
- Odoc_env.subst_type new_env ctyp.ctyp_type)
- tt_excep_decl.cd_args;
- ex_alias = None ;
- ex_loc = { loc_impl = Some loc ; loc_inter = None } ;
- ex_code =
+ te_info = comment_opt;
+ te_type_name =
+ Odoc_env.full_type_name new_env (Name.from_path tt_tyext.tyext_path);
+ te_type_parameters =
+ List.map (fun (ctyp, _) -> Odoc_env.subst_type new_env ctyp.ctyp_type) tt_tyext.tyext_params;
+ te_private = tt_tyext.tyext_private;
+ te_constructors = [];
+ te_loc = { loc_impl = Some loc ; loc_inter = None } ;
+ te_code =
(
- if !Odoc_global.keep_code then
- Some (get_string_of_file loc_start loc_end)
- else
- None
+ if !Odoc_global.keep_code then
+ Some (get_string_of_file loc_start loc_end)
+ else
+ None
) ;
}
in
- (0, new_env, [ Element_exception new_ex ])
+ let rec analyse_extension_constructors maybe_more exts_acc tt_ext_list =
+ match tt_ext_list with
+ [] -> (maybe_more, List.rev exts_acc)
+ | tt_ext :: q ->
+ let complete_name = Name.concat current_module_name tt_ext.ext_name.txt in
+ let ext_loc_end = tt_ext.ext_loc.Location.loc_end.Lexing.pos_cnum in
+ let new_xt =
+ match tt_ext.ext_kind with
+ Text_decl(args, ret_type) ->
+ {
+ xt_name = complete_name;
+ xt_args =
+ List.map (fun ctyp -> Odoc_env.subst_type new_env ctyp.ctyp_type) args;
+ xt_ret =
+ may_map (fun ctyp -> Odoc_env.subst_type new_env ctyp.ctyp_type) ret_type;
+ xt_type_extension = new_te;
+ xt_alias = None;
+ xt_loc = { loc_impl = Some tt_ext.ext_loc ; loc_inter = None } ;
+ xt_text = None;
+ }
+ | Text_rebind(path, _) ->
+ {
+ xt_name = complete_name;
+ xt_args = [];
+ xt_ret = None;
+ xt_type_extension = new_te;
+ xt_alias =
+ Some {
+ xa_name = Odoc_env.full_extension_constructor_name env (Name.from_path path);
+ xa_xt = None;
+ };
+ xt_loc = { loc_impl = Some tt_ext.ext_loc ; loc_inter = None } ;
+ xt_text = None;
+ }
+ in
+ let pos_limit2 =
+ match q with
+ [] -> pos_limit
+ | next :: _ ->
+ next.ext_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let s = get_string_of_file ext_loc_end pos_limit2 in
+ let (maybe_more, comment_opt) = My_ir.just_after_special !file_name s in
+ new_xt.xt_text <- comment_opt;
+ analyse_extension_constructors maybe_more (new_xt :: exts_acc) q
+ in
+ let (maybe_more, exts) = analyse_extension_constructors 0 [] tt_tyext.tyext_constructors in
+ new_te.te_constructors <- exts;
+ (maybe_more, new_env, [ Element_type_extension new_te ])
- | Parsetree.Pstr_exn_rebind {Parsetree.pexrb_name = name} ->
+ | Parsetree.Pstr_exception ext ->
+ let name = ext.Parsetree.pext_name in
(* a new exception is defined *)
let complete_name = Name.concat current_module_name name.txt in
- (* we get the exception rebind in the typed tree *)
- let tt_path =
- try Typedtree_search.search_exception_rebind table name.txt
+ (* we get the exception declaration in the typed tree *)
+ let tt_ext =
+ try Typedtree_search.search_exception table name.txt
with Not_found ->
raise (Failure (Odoc_messages.exception_not_found_in_typedtree complete_name))
in
- let new_env = Odoc_env.add_exception env complete_name in
- let new_ex =
- {
- ex_name = complete_name ;
- ex_info = comment_opt ;
- ex_args = [] ;
- ex_alias = Some { ea_name = (Odoc_env.full_exception_name env (Name.from_path tt_path)) ;
- ea_ex = None ; } ;
- ex_loc = { loc_impl = Some loc ; loc_inter = None } ;
- ex_code = None ;
- }
+ let new_env = Odoc_env.add_extension env complete_name in
+ let new_ext =
+ match tt_ext.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
+ {
+ ex_name = complete_name ;
+ ex_info = comment_opt ;
+ ex_args =
+ List.map
+ (fun ctyp -> Odoc_env.subst_type new_env ctyp.ctyp_type)
+ tt_args;
+ ex_ret =
+ Misc.may_map
+ (fun ctyp -> Odoc_env.subst_type new_env ctyp.ctyp_type)
+ tt_ret_type;
+ ex_alias = None ;
+ ex_loc = { loc_impl = Some loc ; loc_inter = None } ;
+ ex_code =
+ (
+ if !Odoc_global.keep_code then
+ Some (get_string_of_file loc_start loc_end)
+ else
+ None
+ ) ;
+ }
+ | Text_rebind(tt_path, _) ->
+ {
+ ex_name = complete_name ;
+ ex_info = comment_opt ;
+ ex_args = [] ;
+ ex_ret = None ;
+ ex_alias =
+ Some { ea_name =
+ Odoc_env.full_extension_constructor_name
+ env (Name.from_path tt_path) ;
+ ea_ex = None ; } ;
+ ex_loc = { loc_impl = Some loc ; loc_inter = None } ;
+ ex_code = None ;
+ }
in
- (0, new_env, [ Element_exception new_ex ])
+ (0, new_env, [ Element_exception new_ext ])
| Parsetree.Pstr_module {Parsetree.pmb_name=name; pmb_expr=module_expr} ->
(
diff --git a/ocamldoc/odoc_ast.mli b/ocamldoc/odoc_ast.mli
index dc5a2a3ffd..c3db304ea7 100644
--- a/ocamldoc/odoc_ast.mli
+++ b/ocamldoc/odoc_ast.mli
@@ -30,20 +30,15 @@ module Typedtree_search :
@raise Not_found if the module was not found.*)
val search_module : tab -> string -> Typedtree.module_expr
- (** This function returns the [Types.module_type] associated to the given module type name,
+ (** This function returns the [Typedtree.module_type] associated to the given module type name,
in the given table.
@raise Not_found if the module type was not found.*)
val search_module_type : tab -> string -> Typedtree.module_type_declaration
- (** This function returns the [Types.exception_declaration] associated to the given exception name,
+ (** This function returns the [Typedtree.type_extension] associated to the given extension name,
in the given table.
- @raise Not_found if the exception was not found.*)
- val search_exception : tab -> string -> Typedtree.constructor_declaration
-
- (** This function returns the [Path.t] associated to the given exception rebind name,
- in the table.
- @raise Not_found if the exception rebind was not found.*)
- val search_exception_rebind : tab -> string -> Path.t
+ @raise Not_found if the extension was not found.*)
+ val search_extension : tab -> string -> Typedtree.type_extension
(** This function returns the [Typedtree.type_declaration] associated to the given type name,
in the given table.
@@ -55,7 +50,7 @@ module Typedtree_search :
@raise Not_found if the class was not found. *)
val search_class_exp : tab -> string -> (Typedtree.class_expr * (Types.type_expr list))
- (** This function returns the [Types.cltype_declaration] associated to the given class type name,
+ (** This function returns the [Typedtree.class_type_declaration] associated to the given class type name,
in the given table.
@raise Not_found if the class type was not found. *)
val search_class_type_declaration : tab -> string -> Typedtree.class_type_declaration
diff --git a/ocamldoc/odoc_cross.ml b/ocamldoc/odoc_cross.ml
index 70c3c0eb26..28e6ae5bf2 100644
--- a/ocamldoc/odoc_cross.ml
+++ b/ocamldoc/odoc_cross.ml
@@ -15,6 +15,7 @@
module Name = Odoc_name
open Odoc_module
open Odoc_class
+open Odoc_extension
open Odoc_exception
open Odoc_types
open Odoc_value
@@ -60,6 +61,7 @@ module P_alias =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type t _ = (false, false)
+ let p_extension x _ = x.xt_alias <> None
let p_exception e _ = e.ex_alias <> None
let p_attribute a _ = false
let p_method m _ = false
@@ -79,6 +81,9 @@ let (module_aliases : (Name.t, Name.t * alias_state) Hashtbl.t) = Hashtbl.create
(** Couples of module or module type name aliases. *)
let module_and_modtype_aliases = Hashtbl.create 13;;
+(** Couples of extension name aliases. *)
+let extension_aliases = Hashtbl.create 13;;
+
(** Couples of exception name aliases. *)
let exception_aliases = Hashtbl.create 13;;
@@ -102,6 +107,15 @@ let rec build_alias_list = function
| _ -> ()
);
build_alias_list q
+ | (Odoc_search.Res_extension x) :: q ->
+ (
+ match x.xt_alias with
+ None -> ()
+ | Some xa ->
+ Hashtbl.add extension_aliases
+ x.xt_name (xa.xa_name,Alias_to_resolve)
+ );
+ build_alias_list q
| (Odoc_search.Res_exception e) :: q ->
(
match e.ex_alias with
@@ -119,6 +133,7 @@ let rec build_alias_list = function
let get_alias_names module_list =
Hashtbl.clear module_aliases;
Hashtbl.clear module_and_modtype_aliases;
+ Hashtbl.clear extension_aliases;
Hashtbl.clear exception_aliases;
build_alias_list (Search_alias.search module_list 0)
@@ -183,6 +198,7 @@ let kind_name_exists kind =
| RK_class_type -> (fun e -> match e with Odoc_search.Res_class_type _ -> true | _ -> false)
| RK_value -> (fun e -> match e with Odoc_search.Res_value _ -> true | _ -> false)
| RK_type -> (fun e -> match e with Odoc_search.Res_type _ -> true | _ -> false)
+ | RK_extension -> (fun e -> match e with Odoc_search.Res_extension _ -> true | _ -> false)
| RK_exception -> (fun e -> match e with Odoc_search.Res_exception _ -> true | _ -> false)
| RK_attribute -> (fun e -> match e with Odoc_search.Res_attribute _ -> true | _ -> false)
| RK_method -> (fun e -> match e with Odoc_search.Res_method _ -> true | _ -> false)
@@ -200,6 +216,7 @@ let class_exists = kind_name_exists RK_class
let class_type_exists = kind_name_exists RK_class_type
let value_exists = kind_name_exists RK_value
let type_exists = kind_name_exists RK_type
+let extension_exists = kind_name_exists RK_extension
let exception_exists = kind_name_exists RK_exception
let attribute_exists = kind_name_exists RK_attribute
let method_exists = kind_name_exists RK_method
@@ -238,6 +255,14 @@ let lookup_class_type name =
| Odoc_search.Res_class_type c -> c
| _ -> assert false
+let lookup_extension name =
+ match List.find
+ (fun k -> match k with Odoc_search.Res_extension _ -> true | _ -> false)
+ (get_known_elements name)
+ with
+ | Odoc_search.Res_extension x -> x
+ | _ -> assert false
+
let lookup_exception name =
match List.find
(fun k -> match k with Odoc_search.Res_exception _ -> true | _ -> false)
@@ -262,6 +287,8 @@ class scan =
method! scan_type_pre t =
add_known_element t.ty_name (Odoc_search.Res_type t);
true
+ method! scan_extension_constructor x =
+ add_known_element x.xt_name (Odoc_search.Res_extension x)
method! scan_exception e =
add_known_element e.ex_name (Odoc_search.Res_exception e)
method! scan_attribute a =
@@ -298,6 +325,7 @@ type not_found_name =
| NF_c of Name.t
| NF_ct of Name.t
| NF_cct of Name.t
+ | NF_xt of Name.t
| NF_ex of Name.t
(** Functions to find and associate aliases elements. *)
@@ -466,6 +494,7 @@ and associate_in_module_element module_list m_name (acc_b_modif, acc_incomplete_
| Element_class cl -> associate_in_class module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) cl
| Element_class_type ct -> associate_in_class_type module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct
| Element_value _ -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Element_type_extension te -> associate_in_type_extension module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) te
| Element_exception ex ->
(
match ex.ex_alias with
@@ -617,6 +646,29 @@ and associate_in_class_type module_list (acc_b_modif, acc_incomplete_top_module_
in
iter_kind (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) ct.clt_kind
+and associate_in_type_extension module_list (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) te =
+ List.fold_left
+ (fun (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found) xt ->
+ match xt.xt_alias with
+ None -> (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | Some xa ->
+ match xa.xa_xt with
+ Some _ ->
+ (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ | None ->
+ let xt_opt =
+ try Some (lookup_extension xa.xa_name)
+ with Not_found -> None
+ in
+ match xt_opt with
+ None -> (acc_b_modif, (Name.head xt.xt_name) :: acc_incomplete_top_module_names, (NF_xt xa.xa_name) :: acc_names_not_found)
+ | Some x ->
+ xa.xa_xt <- Some x ;
+ (true, acc_incomplete_top_module_names, acc_names_not_found))
+ (acc_b_modif, acc_incomplete_top_module_names, acc_names_not_found)
+ te.te_constructors
+
+
(*************************************************************)
(** Association of types to elements referenced in comments .*)
@@ -630,6 +682,7 @@ let not_found_of_kind kind name =
| RK_class_type -> Odoc_messages.cross_class_type_not_found
| RK_value -> Odoc_messages.cross_value_not_found
| RK_type -> Odoc_messages.cross_type_not_found
+ | RK_extension -> Odoc_messages.cross_extension_not_found
| RK_exception -> Odoc_messages.cross_exception_not_found
| RK_attribute -> Odoc_messages.cross_attribute_not_found
| RK_method -> Odoc_messages.cross_method_not_found
@@ -687,6 +740,7 @@ let rec assoc_comments_text_elements parent_name module_list t_ele =
| Odoc_search.Res_class_type ct -> (ct.clt_name, RK_class_type)
| Odoc_search.Res_value v -> (v.val_name, RK_value)
| Odoc_search.Res_type t -> (t.ty_name, RK_type)
+ | Odoc_search.Res_extension x -> (x.xt_name, RK_extension)
| Odoc_search.Res_exception e -> (e.ex_name, RK_exception)
| Odoc_search.Res_attribute a -> (a.att_value.val_name, RK_attribute)
| Odoc_search.Res_method m -> (m.met_value.val_name, RK_method)
@@ -747,6 +801,7 @@ let rec assoc_comments_text_elements parent_name module_list t_ele =
| RK_class_type -> class_type_exists
| RK_value -> value_exists
| RK_type -> type_exists
+ | RK_extension -> extension_exists
| RK_exception -> exception_exists
| RK_attribute -> attribute_exists
| RK_method -> method_exists
@@ -817,6 +872,8 @@ let rec assoc_comments_module_element parent_name module_list m_ele =
Element_class_type (assoc_comments_class_type module_list ct)
| Element_value v ->
Element_value (assoc_comments_value module_list v)
+ | Element_type_extension te ->
+ Element_type_extension (assoc_comments_type_extension parent_name module_list te)
| Element_exception e ->
Element_exception (assoc_comments_exception module_list e)
| Element_type t ->
@@ -938,6 +995,15 @@ and assoc_comments_value module_list v =
assoc_comments_parameter_list parent module_list v.val_parameters;
v
+and assoc_comments_extension_constructor module_list x =
+ let parent = Name.father x.xt_name in
+ x.xt_text <- ao (assoc_comments_info parent module_list) x.xt_text
+
+and assoc_comments_type_extension parent_name module_list te =
+ te.te_info <- ao (assoc_comments_info parent_name module_list) te.te_info;
+ List.iter (assoc_comments_extension_constructor module_list) te.te_constructors;
+ te
+
and assoc_comments_exception module_list e =
let parent = Name.father e.ex_name in
e.ex_info <- ao (assoc_comments_info parent module_list) e.ex_info ;
@@ -956,6 +1022,7 @@ and assoc_comments_type module_list t =
List.iter
(fun rf -> rf.rf_text <- ao (assoc_comments_info parent module_list) rf.rf_text)
fl
+ | Type_open -> ()
);
t
@@ -1018,6 +1085,7 @@ let associate module_list =
| NF_c n -> Odoc_messages.cross_class_not_found n
| NF_ct n -> Odoc_messages.cross_class_type_not_found n
| NF_cct n -> Odoc_messages.cross_class_or_class_type_not_found n
+ | NF_xt n -> Odoc_messages.cross_extension_not_found n
| NF_ex n -> Odoc_messages.cross_exception_not_found n
);
)
diff --git a/ocamldoc/odoc_dep.ml b/ocamldoc/odoc_dep.ml
index f2934ee3e0..c2949d7334 100644
--- a/ocamldoc/odoc_dep.ml
+++ b/ocamldoc/odoc_dep.ml
@@ -167,11 +167,19 @@ let type_deps t =
ignore (Str.global_substitute re f s)
)
rl
+ | T.Type_open -> ()
);
(match t.T.ty_manifest with
None -> ()
- | Some e ->
+ | Some (T.Object_type fields) ->
+ List.iter
+ (fun r ->
+ let s = Odoc_print.string_of_type_expr r.T.of_type in
+ ignore (Str.global_substitute re f s)
+ )
+ fields
+ | Some (T.Other e) ->
let s = Odoc_print.string_of_type_expr e in
ignore (Str.global_substitute re f s)
);
diff --git a/ocamldoc/odoc_env.ml b/ocamldoc/odoc_env.ml
index 02d1e3a211..3e05905856 100644
--- a/ocamldoc/odoc_env.ml
+++ b/ocamldoc/odoc_env.ml
@@ -26,7 +26,7 @@ type env = {
env_classes : env_element list ;
env_modules : env_element list ;
env_module_types : env_element list ;
- env_exceptions : env_element list ;
+ env_extensions : env_element list ;
}
let empty = {
@@ -36,7 +36,7 @@ let empty = {
env_classes = [] ;
env_modules = [] ;
env_module_types = [] ;
- env_exceptions = [] ;
+ env_extensions = [] ;
}
(** Add a signature to an environment. *)
@@ -52,7 +52,7 @@ let rec add_signature env root ?rel signat =
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_exception (ident, _) -> { env with env_exceptions = (rel_name ident, qualify ident) :: env.env_exceptions }
+ | 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 (* A VOIR : le cas ou c'est un identificateur, dans ce cas on n'a pas de signature *)
@@ -77,9 +77,9 @@ let rec add_signature env root ?rel signat =
in
List.fold_left f env signat
-let add_exception env full_name =
+let add_extension env full_name =
let simple_name = Name.simple full_name in
- { env with env_exceptions = (simple_name, full_name) :: env.env_exceptions }
+ { env with env_extensions = (simple_name, full_name) :: env.env_extensions }
let add_type env full_name =
let simple_name = Name.simple full_name in
@@ -146,11 +146,11 @@ let full_value_name env n =
try List.assoc n env.env_values
with Not_found -> n
-let full_exception_name env n =
- try List.assoc n env.env_exceptions
+let full_extension_constructor_name env n =
+ try List.assoc n env.env_extensions
with Not_found ->
- print_DEBUG ("Exception "^n^" not found with env=");
- List.iter (fun (sn, fn) -> print_DEBUG ("("^sn^", "^fn^")")) env.env_exceptions;
+ print_DEBUG ("Extension "^n^" not found with env=");
+ List.iter (fun (sn, fn) -> print_DEBUG ("("^sn^", "^fn^")")) env.env_extensions;
n
let full_class_name env n =
diff --git a/ocamldoc/odoc_env.mli b/ocamldoc/odoc_env.mli
index cafdd52ed9..4e1e8606d7 100644
--- a/ocamldoc/odoc_env.mli
+++ b/ocamldoc/odoc_env.mli
@@ -22,7 +22,7 @@ val empty : env
(** Extending an environment *)
val add_signature : env -> string -> ?rel:string -> Types.signature -> env
-val add_exception : env -> Odoc_name.t -> env
+val add_extension : env -> Odoc_name.t -> env
val add_type : env -> Odoc_name.t -> env
val add_value : env -> Odoc_name.t -> env
val add_module : env -> Odoc_name.t -> env
@@ -48,8 +48,8 @@ val full_type_name : env -> Odoc_name.t -> Odoc_name.t
(** Get the fully qualified value name from a name.*)
val full_value_name : env -> Odoc_name.t -> Odoc_name.t
-(** Get the fully qualified exception name from a name.*)
-val full_exception_name : env -> Odoc_name.t -> Odoc_name.t
+(** Get the fully qualified extension name from a name.*)
+val full_extension_constructor_name : env -> Odoc_name.t -> Odoc_name.t
(** Get the fully qualified class name from a name.*)
val full_class_name : env -> Odoc_name.t -> Odoc_name.t
diff --git a/ocamldoc/odoc_exception.ml b/ocamldoc/odoc_exception.ml
index a62cb7b7d5..b0e21196cc 100644
--- a/ocamldoc/odoc_exception.ml
+++ b/ocamldoc/odoc_exception.ml
@@ -23,6 +23,7 @@ and t_exception = {
ex_name : Name.t ;
mutable ex_info : Odoc_types.info option ; (** optional user information *)
ex_args : Types.type_expr list ; (** the types of the parameters *)
+ ex_ret: Types.type_expr option ; (** the optional return type *)
ex_alias : exception_alias option ;
mutable ex_loc : Odoc_types.location ;
mutable ex_code : string option ;
diff --git a/ocamldoc/odoc_extension.ml b/ocamldoc/odoc_extension.ml
new file mode 100644
index 0000000000..0a08419530
--- /dev/null
+++ b/ocamldoc/odoc_extension.ml
@@ -0,0 +1,46 @@
+(***********************************************************************)
+(* OCamldoc *)
+(* *)
+(* 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
+(** Representation and manipulation of type extensions. *)
+
+module Name = Odoc_name
+
+type private_flag = Asttypes.private_flag =
+ Private | Public
+
+type extension_alias = {
+ xa_name : Name.t ;
+ mutable xa_xt : t_extension_constructor option ;
+ }
+
+and t_extension_constructor = {
+ xt_name : Name.t ;
+ xt_args: Types.type_expr list ; (** the types of the parameters *)
+ xt_ret: Types.type_expr option ; (** the optional return type of the extension *)
+ xt_type_extension: t_type_extension ; (** the type extension containing this constructor *)
+ xt_alias: extension_alias option ;
+ mutable xt_loc: Odoc_types.location ;
+ mutable xt_text: Odoc_types.info option ; (** optional user description *)
+ }
+
+and t_type_extension = {
+ mutable te_info : Odoc_types.info option ; (** optional user information *)
+ te_type_name : Name.t;
+ te_type_parameters : Types.type_expr list;
+ te_private : private_flag;
+ mutable te_constructors: t_extension_constructor list;
+ mutable te_loc : Odoc_types.location ;
+ mutable te_code : string option ;
+ }
+
+let extension_constructors te = te.te_constructors
diff --git a/ocamldoc/odoc_html.ml b/ocamldoc/odoc_html.ml
index 3bee9838b6..96f2dfc7e5 100644
--- a/ocamldoc/odoc_html.ml
+++ b/ocamldoc/odoc_html.ml
@@ -18,6 +18,7 @@ open Odoc_info
open Parameter
open Value
open Type
+open Extension
open Exception
open Class
open Module
@@ -42,6 +43,9 @@ module Naming =
(** The prefix for functions marks. *)
let mark_function = "FUN"
+ (** The prefix for extensions marks. *)
+ let mark_extension = "EXTENSION"
+
(** The prefix for exceptions marks. *)
let mark_exception = "EXCEPTION"
@@ -100,6 +104,10 @@ module Naming =
let recfield_target t f = target mark_type_elt
(Printf.sprintf "%s.%s" (Name.simple t.ty_name) f.rf_name)
+ (** Return the link target for the given object field. *)
+ let objfield_target t f = target mark_type_elt
+ (Printf.sprintf "%s.%s" (Name.simple t.ty_name) f.of_name)
+
(** Return the complete link target for the given type. *)
let complete_type_target t = complete_target mark_type t.ty_name
@@ -110,6 +118,12 @@ module Naming =
let complete_const_target = complete_recfield_target
+ (** Return the link target for the given extension. *)
+ let extension_target x = target mark_extension (Name.simple x.xt_name)
+
+ (** Return the complete link target for the given extension. *)
+ let complete_extension_target x = complete_target mark_extension x.xt_name
+
(** Return the link target for the given exception. *)
let exception_target e = target mark_exception (Name.simple e.ex_name)
@@ -261,9 +275,9 @@ class virtual text =
List.iter (self#html_of_text_element b) t
(** Print the html code for the [text_element] in parameter. *)
- method html_of_text_element b te =
+ method html_of_text_element b txt =
print_DEBUG "text::html_of_text_element";
- match te with
+ match txt with
| Odoc_info.Raw s -> self#html_of_Raw b s
| Odoc_info.Code s -> self#html_of_Code b s
| Odoc_info.CodePre s -> self#html_of_CodePre b s
@@ -454,6 +468,7 @@ class virtual text =
(html_file, h name)
| Odoc_info.RK_value -> (Naming.complete_target Naming.mark_value name, h name)
| Odoc_info.RK_type -> (Naming.complete_target Naming.mark_type name, h name)
+ | Odoc_info.RK_extension -> (Naming.complete_target Naming.mark_extension name, h name)
| Odoc_info.RK_exception -> (Naming.complete_target Naming.mark_exception name, h name)
| Odoc_info.RK_attribute -> (Naming.complete_target Naming.mark_attribute name, h name)
| Odoc_info.RK_method -> (Naming.complete_target Naming.mark_method name, h name)
@@ -515,6 +530,7 @@ class virtual text =
in
bp b "<ul class=\"indexlist\">\n";
index_if_not_empty self#list_types self#index_types Odoc_messages.index_of_types;
+ index_if_not_empty self#list_extensions self#index_extensions Odoc_messages.index_of_extensions;
index_if_not_empty self#list_exceptions self#index_exceptions Odoc_messages.index_of_exceptions;
index_if_not_empty self#list_values self#index_values Odoc_messages.index_of_values;
index_if_not_empty self#list_attributes self#index_attributes Odoc_messages.index_of_attributes;
@@ -527,6 +543,8 @@ class virtual text =
method virtual list_types : Odoc_info.Type.t_type list
method virtual index_types : string
+ method virtual list_extensions : Odoc_info.Extension.t_extension_constructor list
+ method virtual index_extensions : string
method virtual list_exceptions : Odoc_info.Exception.t_exception list
method virtual index_exceptions : string
method virtual list_values : Odoc_info.Value.t_value list
@@ -888,6 +906,8 @@ class html =
method index_values = Printf.sprintf "%s_values.html" self#index_prefix
(** The file for the index of types. *)
method index_types = Printf.sprintf "%s_types.html" self#index_prefix
+ (** The file for the index of extensions. *)
+ method index_extensions = Printf.sprintf "%s_extensions.html" self#index_prefix
(** The file for the index of exceptions. *)
method index_exceptions = Printf.sprintf "%s_exceptions.html" self#index_prefix
(** The file for the index of attributes. *)
@@ -913,6 +933,9 @@ class html =
(** The list of values. Filled in the [generate] method. *)
val mutable list_values = []
method list_values = list_values
+ (** The list of extensions. Filled in the [generate] method. *)
+ val mutable list_extensions = []
+ method list_extensions = list_extensions
(** The list of exceptions. Filled in the [generate] method. *)
val mutable list_exceptions = []
method list_exceptions = list_exceptions
@@ -1012,6 +1035,7 @@ class html =
)
);
link_if_not_empty self#list_types Odoc_messages.index_of_types self#index_types;
+ link_if_not_empty self#list_extensions Odoc_messages.index_of_extensions self#index_extensions;
link_if_not_empty self#list_exceptions Odoc_messages.index_of_exceptions self#index_exceptions;
link_if_not_empty self#list_values Odoc_messages.index_of_values self#index_values;
link_if_not_empty self#list_attributes Odoc_messages.index_of_attributes self#index_attributes;
@@ -1321,7 +1345,7 @@ class html =
self#html_of_module_type_kind b father p.mp_kind;
self#html_of_text b [ Code (") "^s_arrow)]
- method html_of_module_element b father ele =
+ method html_of_module_element b m_name ele =
match ele with
Element_module m ->
self#html_of_module b ~complete: false m
@@ -1335,6 +1359,8 @@ class html =
self#html_of_class_type b ~complete: false ct
| Element_value v ->
self#html_of_value b v
+ | Element_type_extension te ->
+ self#html_of_type_extension b m_name te
| Element_exception e ->
self#html_of_exception b e
| Element_type t ->
@@ -1424,6 +1450,84 @@ class html =
self#html_of_described_parameter_list b (Name.father v.val_name) v.val_parameters
)
+ (** Print html code for a type extension. *)
+ method html_of_type_extension b m_name te =
+ Odoc_info.reset_type_names ();
+ bs b "<pre><code>";
+ bs b ((self#keyword "type")^" ");
+ let s = Odoc_info.string_of_type_extension_param_list te in
+ let s2 = newline_to_indented_br s in
+ bs b "<code class=\"type\">";
+ bs b (self#create_fully_qualified_idents_links m_name s2);
+ bs b "</code>";
+ (match te.te_type_parameters with [] -> () | _ -> bs b " ");
+ bs b (self#create_fully_qualified_idents_links m_name te.te_type_name);
+ bs b " += ";
+ if te.te_private = Asttypes.Private then bs b "private ";
+ bs b "</code></pre>";
+ bs b "<table class=\"typetable\">\n";
+ let print_one x =
+ let father = Name.father x.xt_name in
+ bs b "<tr>\n<td align=\"left\" valign=\"top\" >\n";
+ bs b "<code>";
+ bs b (self#keyword "|");
+ bs b "</code></td>\n<td align=\"left\" valign=\"top\" >\n";
+ bs b "<code>";
+ bp b "<span id=\"%s\">%s</span>"
+ (Naming.extension_target x)
+ (Name.simple x.xt_name);
+ (
+ match x.xt_args, x.xt_ret with
+ [], None -> ()
+ | l,None ->
+ bs b (" " ^ (self#keyword "of") ^ " ");
+ self#html_of_type_expr_list ~par: false b father " * " l;
+ | [],Some r ->
+ bs b (" " ^ (self#keyword ":") ^ " ");
+ self#html_of_type_expr b father r;
+ | l,Some r ->
+ bs b (" " ^ (self#keyword ":") ^ " ");
+ self#html_of_type_expr_list ~par: false b father " * " l;
+ bs b (" " ^ (self#keyword "->") ^ " ");
+ self#html_of_type_expr b father r;
+ );
+ (
+ match x.xt_alias with
+ None -> ()
+ | Some xa ->
+ bs b " = ";
+ (
+ match xa.xa_xt with
+ None -> bs b xa.xa_name
+ | Some x ->
+ bp b "<a href=\"%s\">%s</a>" (Naming.complete_extension_target x) x.xt_name
+ )
+ );
+ bs b "</code></td>\n";
+ (
+ match x.xt_text with
+ None -> ()
+ | Some t ->
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >";
+ bs b "<code>";
+ bs b "(*";
+ bs b "</code></td>";
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >";
+ self#html_of_info b (Some t);
+ bs b "</td>";
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"bottom\" >";
+ bs b "<code>";
+ bs b "*)";
+ bs b "</code></td>";
+ );
+ bs b "\n</tr>"
+ in
+ print_concat b "\n" print_one te.te_constructors;
+ bs b "</table>\n";
+ bs b "\n";
+ self#html_of_info b te.te_info;
+ bs b "\n"
+
(** Print html code for an exception. *)
method html_of_exception b e =
Odoc_info.reset_type_names ();
@@ -1434,12 +1538,21 @@ class html =
bs b (Name.simple e.ex_name);
bs b "</span>";
(
- match e.ex_args with
- [] -> ()
- | _ ->
- bs b (" "^(self#keyword "of")^" ");
- self#html_of_type_expr_list
- ~par: false b (Name.father e.ex_name) " * " e.ex_args
+ match e.ex_args, e.ex_ret with
+ [], None -> ()
+ | l,None ->
+ bs b (" "^(self#keyword "of")^" ");
+ self#html_of_type_expr_list
+ ~par: false b (Name.father e.ex_name) " * " e.ex_args
+ | [],Some r ->
+ bs b (" " ^ (self#keyword ":") ^ " ");
+ self#html_of_type_expr b (Name.father e.ex_name) r;
+ | l,Some r ->
+ bs b (" " ^ (self#keyword ":") ^ " ");
+ self#html_of_type_expr_list
+ ~par: false b (Name.father e.ex_name) " * " l;
+ bs b (" " ^ (self#keyword "->") ^ " ");
+ self#html_of_type_expr b (Name.father e.ex_name) r;
);
(
match e.ex_alias with
@@ -1460,12 +1573,32 @@ class html =
method html_of_type b t =
Odoc_info.reset_type_names ();
let father = Name.father t.ty_name in
+ let print_field_prefix () =
+ bs b "<tr>\n<td align=\"left\" valign=\"top\" >\n";
+ bs b "<code>&nbsp;&nbsp;</code>";
+ bs b "</td>\n<td align=\"left\" valign=\"top\" >\n";
+ bs b "<code>";
+ in
+ let print_field_comment = function
+ | None -> ()
+ | Some t ->
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >";
+ bs b "<code>";
+ bs b "(*";
+ bs b "</code></td>";
+ bs b "<td class=\"typefieldcomment\" align=\"left\" valign=\"top\" >";
+ self#html_of_info b (Some t);
+ bs b "</td><td class=\"typefieldcomment\" align=\"left\" valign=\"bottom\" >";
+ bs b "<code>*)</code></td>"
+ in
bs b
(match t.ty_manifest, t.ty_kind with
- None, Type_abstract -> "\n<pre>"
+ None, Type_abstract
+ | None, Type_open -> "\n<pre>"
| None, Type_variant _
| None, Type_record _ -> "\n<pre><code>"
- | Some _, Type_abstract -> "\n<pre>"
+ | Some _, Type_abstract
+ | Some _, Type_open -> "\n<pre>"
| Some _, Type_variant _
| Some _, Type_record _ -> "\n<pre>"
);
@@ -1479,7 +1612,25 @@ class html =
(
match t.ty_manifest with
None -> ()
- | Some typ ->
+ | Some (Object_type fields) ->
+ bs b "= ";
+ if priv then bs b "private ";
+ bs b "&lt;</pre>";
+ bs b "<table class=\"typetable\">\n" ;
+ let print_one f =
+ print_field_prefix () ;
+ bp b "<span id=\"%s\">%s</span>&nbsp;: "
+ (Naming.objfield_target t f)
+ f.of_name;
+ self#html_of_type_expr b father f.of_type;
+ bs b ";</code></td>\n";
+ print_field_comment f.of_text ;
+ bs b "\n</tr>"
+ in
+ print_concat b "\n" print_one fields;
+ bs b "</table>\n>\n";
+ bs b " "
+ | Some (Other typ) ->
bs b "= ";
if priv then bs b "private ";
self#html_of_type_expr b father typ;
@@ -1582,6 +1733,9 @@ class html =
in
print_concat b "\n" print_one l;
bs b "</table>\n}\n"
+ | Type_open ->
+ bs b "= ..";
+ bs b "</pre>"
);
bs b "\n";
self#html_of_info b t.ty_info;
@@ -2313,7 +2467,7 @@ class html =
bs b "<hr width=\"100%\">\n";
(* module elements *)
List.iter
- (self#html_of_module_element b (Name.father mt.mt_name))
+ (self#html_of_module_element b mt.mt_name)
(Module.module_type_elements mt);
bs b "</body></html>";
@@ -2396,7 +2550,7 @@ class html =
(* module elements *)
List.iter
- (self#html_of_module_element b (Name.father modu.m_name))
+ (self#html_of_module_element b modu.m_name)
(Module.module_elements modu);
bs b "</body></html>";
@@ -2474,6 +2628,16 @@ class html =
Odoc_messages.index_of_values
self#index_values
+ (** Generate the extensions index in the file [index_extensions.html]. *)
+ method generate_extensions_index module_list =
+ self#generate_elements_index
+ self#list_extensions
+ (fun x -> x.xt_name)
+ (fun x -> x.xt_type_extension.te_info)
+ (fun x -> Naming.complete_extension_target x)
+ Odoc_messages.index_of_extensions
+ self#index_extensions
+
(** Generate the exceptions index in the file [index_exceptions.html]. *)
method generate_exceptions_index module_list =
self#generate_elements_index
@@ -2561,6 +2725,7 @@ class html =
self#init_style ;
(* init the lists of elements *)
list_values <- Odoc_info.Search.values module_list ;
+ list_extensions <- Odoc_info.Search.extensions module_list ;
list_exceptions <- Odoc_info.Search.exceptions module_list ;
list_types <- Odoc_info.Search.types module_list ;
list_attributes <- Odoc_info.Search.attributes module_list ;
@@ -2612,6 +2777,7 @@ class html =
try
self#generate_index module_list;
self#generate_values_index module_list ;
+ self#generate_extensions_index module_list ;
self#generate_exceptions_index module_list ;
self#generate_types_index module_list ;
self#generate_attributes_index module_list ;
diff --git a/ocamldoc/odoc_info.ml b/ocamldoc/odoc_info.ml
index 4a6c214190..c576e1000b 100644
--- a/ocamldoc/odoc_info.ml
+++ b/ocamldoc/odoc_info.ml
@@ -19,6 +19,7 @@ type ref_kind = Odoc_types.ref_kind =
| RK_class_type
| RK_value
| RK_type
+ | RK_extension
| RK_exception
| RK_attribute
| RK_method
@@ -90,6 +91,7 @@ let dummy_loc = { loc_impl = None ; loc_inter = None }
module Name = Odoc_name
module Parameter = Odoc_parameter
+module Extension = Odoc_extension
module Exception = Odoc_exception
module Type = Odoc_type
module Value = Odoc_value
@@ -128,6 +130,8 @@ let string_of_type_list ?par sep type_list = Odoc_str.string_of_type_list ?par s
let string_of_type_param_list t = Odoc_str.string_of_type_param_list t
+let string_of_type_extension_param_list te = Odoc_str.string_of_type_extension_param_list te
+
let string_of_class_type_param_list l = Odoc_str.string_of_class_type_param_list l
let string_of_module_type = Odoc_print.string_of_module_type
@@ -140,6 +144,8 @@ let string_of_info i = Odoc_misc.string_of_info i
let string_of_type t = Odoc_str.string_of_type t
+let string_of_type_extension te = Odoc_str.string_of_type_extension te
+
let string_of_exception e = Odoc_str.string_of_exception e
let string_of_value v = Odoc_str.string_of_value v
@@ -290,6 +296,7 @@ module Search =
| Res_class_type of Class.t_class_type
| Res_value of Value.t_value
| Res_type of Type.t_type
+ | Res_extension of Extension.t_extension_constructor
| Res_exception of Exception.t_exception
| Res_attribute of Value.t_attribute
| Res_method of Value.t_method
@@ -302,6 +309,7 @@ module Search =
let search_by_name = Odoc_search.Search_by_name.search
let values = Odoc_search.values
+ let extensions = Odoc_search.extensions
let exceptions = Odoc_search.exceptions
let types = Odoc_search.types
let attributes = Odoc_search.attributes
diff --git a/ocamldoc/odoc_info.mli b/ocamldoc/odoc_info.mli
index 76e28df64b..e9a9705c7f 100644
--- a/ocamldoc/odoc_info.mli
+++ b/ocamldoc/odoc_info.mli
@@ -20,6 +20,7 @@ type ref_kind = Odoc_types.ref_kind =
| RK_class_type
| RK_value
| RK_type
+ | RK_extension
| RK_exception
| RK_attribute
| RK_method
@@ -169,6 +170,47 @@ module Parameter :
val type_by_name : parameter -> string -> Types.type_expr
end
+(** Representation and manipulation of extensions. *)
+module Extension :
+ sig
+ type private_flag = Odoc_extension.private_flag =
+ Private | Public
+
+ (** Used when the extension is a rebind of another extension,
+ when we have [extension Xt = Target_xt].*)
+ type extension_alias = Odoc_extension.extension_alias =
+ {
+ xa_name : Name.t ; (** The complete name of the target extension. *)
+ mutable xa_xt : t_extension_constructor option ; (** The target extension, if we found it.*)
+ }
+
+ and t_extension_constructor = Odoc_extension.t_extension_constructor =
+ {
+ xt_name : Name.t ;
+ xt_args: Types.type_expr list ; (** the types of the parameters *)
+ xt_ret: Types.type_expr option ; (** the optional return type of the extension *)
+ xt_type_extension: t_type_extension ; (** the type extension containing this constructor *)
+ xt_alias: extension_alias option ; (** [None] when the extension is not a rebind. *)
+ mutable xt_loc: Odoc_types.location ;
+ mutable xt_text: Odoc_types.info option ; (** optional user description *)
+ }
+
+ and t_type_extension = Odoc_extension.t_type_extension =
+ {
+ mutable te_info : info option ; (** Information found in the optional associated comment. *)
+ te_type_name : Name.t ; (** The type of the extension *)
+ te_type_parameters : Types.type_expr list;
+ te_private : private_flag ;
+ mutable te_constructors: t_extension_constructor list;
+ mutable te_loc : location ;
+ mutable te_code : string option ;
+ }
+
+ (** Access to the extensions in a group. *)
+ val extension_constructors : t_type_extension -> t_extension_constructor list
+
+ end
+
(** Representation and manipulation of exceptions. *)
module Exception :
sig
@@ -185,6 +227,7 @@ module Exception :
ex_name : Name.t ;
mutable ex_info : info option ; (** Information found in the optional associated comment. *)
ex_args : Types.type_expr list ; (** The types of the parameters. *)
+ ex_ret : Types.type_expr option ; (** The the optional return type of the exception. *)
ex_alias : exception_alias option ; (** [None] when the exception is not a rebind. *)
mutable ex_loc : location ;
mutable ex_code : string option ;
@@ -222,6 +265,17 @@ module Type :
(** constructors *)
| Type_record of record_field list
(** fields *)
+ | Type_open (** Type is open *)
+
+ type object_field = Odoc_type.object_field = {
+ of_name : string ;
+ of_type : Types.type_expr ;
+ mutable of_text : Odoc_types.info option ; (** optional user description *)
+ }
+
+ type type_manifest = Odoc_type.type_manifest =
+ | Other of Types.type_expr (** Type manifest directly taken from Typedtre. *)
+ | Object_type of object_field list
(** Representation of a type. *)
type t_type = Odoc_type.t_type =
@@ -232,7 +286,7 @@ module Type :
(** type parameters: (type, covariant, contravariant) *)
ty_kind : type_kind; (** Type kind. *)
ty_private : private_flag; (** Private or public type. *)
- ty_manifest : Types.type_expr option; (** Type manifest. *)
+ ty_manifest : type_manifest option ;
mutable ty_loc : location ;
mutable ty_code : string option;
}
@@ -410,6 +464,7 @@ module Module :
| Element_class of Class.t_class
| Element_class_type of Class.t_class_type
| Element_value of Value.t_value
+ | Element_type_extension of Extension.t_type_extension
| Element_exception of Exception.t_exception
| Element_type of Type.t_type
| Element_module_comment of text
@@ -518,6 +573,9 @@ module Module :
(** Access to the included modules of a module. *)
val module_included_modules : ?trans:bool-> t_module -> included_module list
+ (** Access to the type extensions of a module. *)
+ val module_type_extensions : ?trans:bool-> t_module -> Extension.t_type_extension list
+
(** Access to the exceptions of a module. *)
val module_exceptions : ?trans:bool-> t_module -> Exception.t_exception list
@@ -630,6 +688,10 @@ val string_of_type_list : ?par: bool -> string -> Types.type_expr list -> string
for the given type. *)
val string_of_type_param_list : Type.t_type -> string
+(** This function returns a string to represent the list of type parameters
+ for the given type extension. *)
+val string_of_type_extension_param_list : Extension.t_type_extension -> string
+
(** This function returns a string to represent the given list of
type parameters of a class or class type,
with a given separator. *)
@@ -659,6 +721,9 @@ val string_of_info : info -> string
(** @return a string to describe the given type. *)
val string_of_type : Type.t_type -> string
+(** @return a string to describe the given type extension. *)
+val string_of_type_extension : Extension.t_type_extension -> string
+
(** @return a string to describe the given exception. *)
val string_of_exception : Exception.t_exception -> string
@@ -789,6 +854,7 @@ module Search :
| Res_class_type of Class.t_class_type
| Res_value of Value.t_value
| Res_type of Type.t_type
+ | Res_extension of Extension.t_extension_constructor
| Res_exception of Exception.t_exception
| Res_attribute of Value.t_attribute
| Res_method of Value.t_method
@@ -805,6 +871,9 @@ module Search :
(** A function to search all the values in a list of modules. *)
val values : Module.t_module list -> Value.t_value list
+ (** A function to search all the extensions in a list of modules. *)
+ val extensions : Module.t_module list -> Extension.t_extension_constructor list
+
(** A function to search all the exceptions in a list of modules. *)
val exceptions : Module.t_module list -> Exception.t_exception list
@@ -844,11 +913,27 @@ module Scan :
method scan_type_const : Type.t_type -> Type.variant_constructor -> unit
method scan_type_recfield : Type.t_type -> Type.record_field -> unit
method scan_type : Type.t_type -> unit
+ method scan_extension_constructor : Extension.t_extension_constructor -> unit
method scan_exception : Exception.t_exception -> unit
method scan_attribute : Value.t_attribute -> unit
method scan_method : Value.t_method -> unit
method scan_included_module : Module.included_module -> unit
+ (** Scan of a type extension *)
+
+ (** Overide this method to perform controls on the extension's type,
+ private and info. This method is called before scanning the
+ extension's constructors.
+ @return true if the extension's constructors must be scanned.*)
+ method scan_type_extension_pre : Extension.t_type_extension -> bool
+
+ (** This method scans the constructors of the given type extension. *)
+ method scan_type_extension_constructors : Extension.t_type_extension -> unit
+
+ (** Scan of a type extension. Should not be overridden. It calls [scan_type_extension_pre]
+ and if [scan_type_extension_pre] returns [true], then it calls scan_type_extension_constructors.*)
+ method scan_type_extension : Extension.t_type_extension -> unit
+
(** Scan of a class. *)
(** Scan of a comment inside a class. *)
diff --git a/ocamldoc/odoc_latex.ml b/ocamldoc/odoc_latex.ml
index 90dba5fa3f..d0ef4310bb 100644
--- a/ocamldoc/odoc_latex.ml
+++ b/ocamldoc/odoc_latex.ml
@@ -18,6 +18,7 @@ open Odoc_info
open Parameter
open Value
open Type
+open Extension
open Exception
open Class
open Module
@@ -37,6 +38,7 @@ let latex_titles = ref [
let latex_value_prefix = ref Odoc_messages.default_latex_value_prefix
let latex_type_prefix = ref Odoc_messages.default_latex_type_prefix
let latex_type_elt_prefix = ref Odoc_messages.default_latex_type_elt_prefix
+let latex_extension_prefix = ref Odoc_messages.default_latex_extension_prefix
let latex_exception_prefix = ref Odoc_messages.default_latex_exception_prefix
let latex_module_prefix = ref Odoc_messages.default_latex_module_prefix
let latex_module_type_prefix = ref Odoc_messages.default_latex_module_type_prefix
@@ -234,6 +236,9 @@ class text =
(** Make a correct label from a module type name. *)
method module_type_label ?no_ name = !latex_module_type_prefix^(self#label ?no_ name)
+ (** Make a correct label from an extension name. *)
+ method extension_label ?no_ name = !latex_extension_prefix^(self#label ?no_ name)
+
(** Make a correct label from an exception name. *)
method exception_label ?no_ name = !latex_exception_prefix^(self#label ?no_ name)
@@ -257,8 +262,8 @@ class text =
List.iter (self#latex_of_text_element fmt) t
(** Print the LaTeX code for the [text_element] in parameter. *)
- method latex_of_text_element fmt te =
- match te with
+ method latex_of_text_element fmt txt =
+ match txt with
| Odoc_info.Raw s -> self#latex_of_Raw fmt s
| Odoc_info.Code s -> self#latex_of_Code fmt s
| Odoc_info.CodePre s -> self#latex_of_CodePre fmt s
@@ -411,6 +416,7 @@ class text =
| Odoc_info.RK_class_type -> self#class_type_label
| Odoc_info.RK_value -> self#value_label
| Odoc_info.RK_type -> self#type_label
+ | Odoc_info.RK_extension -> self#extension_label
| Odoc_info.RK_exception -> self#exception_label
| Odoc_info.RK_attribute -> self#attribute_label
| Odoc_info.RK_method -> self#method_label
@@ -533,53 +539,181 @@ class latex =
let priv = t.ty_private = Asttypes.Private in
(
match t.ty_manifest with
- None -> ()
- | Some typ ->
+ | Some (Other typ) ->
p fmt2 " = %s%s" (if priv then "private " else "") (self#normal_type mod_name typ)
+ | _ -> ()
);
let s_type3 =
p fmt2
" %s"
(
match t.ty_kind with
- Type_abstract -> ""
+ Type_abstract ->
+ begin match t.ty_manifest with
+ | Some (Object_type _) ->
+ "= " ^ (if priv then "private" else "") ^ " <"
+ | _ -> ""
+ end
| Type_variant _ -> "="^(if priv then " private" else "")
| Type_record _ -> "= "^(if priv then "private " else "")^"{"
+ | Type_open -> "= .."
) ;
flush2 ()
in
let defs =
+ let entry_comment = function
+ | None -> []
+ | Some t ->
+ let s =
+ ps fmt2 "\\begin{ocamldoccomment}\n";
+ self#latex_of_info fmt2 (Some t);
+ ps fmt2 "\n\\end{ocamldoccomment}\n";
+ flush2 ()
+ in
+ [ Latex s]
+ in
match t.ty_kind with
- Type_abstract -> []
+ | Type_abstract ->
+ begin match t.ty_manifest with
+ | Some (Object_type l) ->
+ let fields =
+ List.map (fun r ->
+ let s_field =
+ p fmt2
+ "@[<h 6> %s :@ %s ;"
+ r.of_name
+ (self#normal_type mod_name r.of_type);
+ flush2 ()
+ in
+ [ CodePre s_field ] @ (entry_comment r.of_text)
+ ) l
+ in
+ List.flatten fields @ [ CodePre ">" ]
+
+ | None | Some (Other _) -> []
+ end
| Type_variant l ->
- (List.flatten
- (List.map
- (fun constr ->
- let s_cons =
- p fmt2 "@[<h 6> | %s" constr.vc_name;
- (
- match constr.vc_args, constr.vc_ret with
- [], None -> ()
- | l, None ->
- p fmt2 " %s@ %s"
- "of"
- (self#normal_type_list ~par: false mod_name " * " l)
- | [], Some r ->
- p fmt2 " %s@ %s"
- ":"
- (self#normal_type mod_name r)
- | l, Some r ->
- p fmt2 " %s@ %s@ %s@ %s"
- ":"
- (self#normal_type_list ~par: false mod_name " * " l)
- "->"
- (self#normal_type mod_name r)
- );
- flush2 ()
+ let constructors =
+ List.map (fun constr ->
+ let s_cons =
+ p fmt2 "@[<h 6> | %s" constr.vc_name ;
+ begin match constr.vc_args, constr.vc_ret with
+ | [], None -> ()
+ | l, None ->
+ p fmt2 " of@ %s"
+ (self#normal_type_list ~par: false mod_name " * " l)
+ | [], Some r ->
+ p fmt2 " :@ %s"
+ (self#normal_type mod_name r)
+ | l, Some r ->
+ p fmt2 " :@ %s@ %s@ %s"
+ (self#normal_type_list ~par: false mod_name " * " l)
+ "->"
+ (self#normal_type mod_name r)
+ end ;
+ flush2 ()
+ in
+ [ CodePre s_cons ] @ (entry_comment constr.vc_text)
+ ) l
+ in
+ List.flatten constructors
+ | Type_record l ->
+ let fields =
+ List.map (fun r ->
+ let s_field =
+ p fmt2
+ "@[<h 6> %s%s :@ %s ;"
+ (if r.rf_mutable then "mutable " else "")
+ r.rf_name
+ (self#normal_type mod_name r.rf_type);
+ flush2 ()
+ in
+ [ CodePre s_field ] @ (entry_comment r.rf_text)
+ ) l
+ in
+ List.flatten fields @ [ CodePre "}" ]
+ | Type_open ->
+ (* FIXME ? *)
+ []
+ in
+ let defs2 = (CodePre s_type3) :: defs in
+ let rec iter = function
+ [] -> []
+ | [e] -> [e]
+ | (CodePre s1) :: (CodePre s2) :: q ->
+ iter ((CodePre (s1^"\n"^s2)) :: q)
+ | e :: q ->
+ e :: (iter q)
+ in
+ (iter defs2) @
+ [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")] @
+ (self#text_of_info t.ty_info)
+ in
+ self#latex_of_text fmt
+ ((Latex (self#make_label (self#type_label t.ty_name))) :: text)
+
+ (** Print LaTeX code for a type extension. *)
+ method latex_of_type_extension mod_name fmt te =
+ let text =
+ let (fmt2, flush2) = new_fmt () in
+ Odoc_info.reset_type_names () ;
+ Format.fprintf fmt2 "@[<h 2>type ";
+ (
+ match te.te_type_parameters with
+ [] -> ()
+ | [p] ->
+ ps fmt2 (self#normal_type mod_name p);
+ ps fmt2 " "
+ | l ->
+ ps fmt2 "(";
+ print_concat fmt2 ", " (fun p -> ps fmt2 (self#normal_type mod_name p)) l;
+ ps fmt2 ") "
+ );
+ ps fmt2 (self#relative_idents mod_name te.te_type_name);
+ p fmt2 " +=%s" (if te.te_private = Asttypes.Private then " private" else "") ;
+ let s_type3 = flush2 () in
+ let defs =
+ (List.flatten
+ (List.map
+ (fun x ->
+ let father = Name.father x.xt_name in
+ let s_cons =
+ p fmt2 "@[<h 6> | %s" (Name.simple x.xt_name);
+ (
+ match x.xt_args, x.xt_ret with
+ [], None -> ()
+ | l, None ->
+ p fmt2 " %s@ %s"
+ "of"
+ (self#normal_type_list ~par: false father " * " l)
+ | [], Some r ->
+ p fmt2 " %s@ %s"
+ ":"
+ (self#normal_type father r)
+ | l, Some r ->
+ p fmt2 " %s@ %s@ %s@ %s"
+ ":"
+ (self#normal_type_list ~par: false father " * " l)
+ "->"
+ (self#normal_type father r)
+ );
+ (
+ match x.xt_alias with
+ None -> ()
+ | Some xa ->
+ p fmt2 " = %s"
+ (
+ match xa.xa_xt with
+ None -> xa.xa_name
+ | Some x -> x.xt_name
+ )
+ );
+ flush2 ()
in
- [ CodePre s_cons ] @
- (match constr.vc_text with
+ [ Latex (self#make_label (self#extension_label x.xt_name));
+ CodePre s_cons ] @
+ (match x.xt_text with
None -> []
| Some t ->
let s =
@@ -591,38 +725,9 @@ class latex =
[ Latex s]
)
)
- l
+ te.te_constructors
)
)
- | Type_record l ->
- (List.flatten
- (List.map
- (fun r ->
- let s_field =
- p fmt2
- "@[<h 6> %s%s :@ %s ;"
- (if r.rf_mutable then "mutable " else "")
- r.rf_name
- (self#normal_type mod_name r.rf_type);
- flush2 ()
- in
- [ CodePre s_field ] @
- (match r.rf_text with
- None -> []
- | Some t ->
- let s =
- ps fmt2 "\\begin{ocamldoccomment}\n";
- self#latex_of_info fmt2 (Some t);
- ps fmt2 "\n\\end{ocamldoccomment}\n";
- flush2 ()
- in
- [ Latex s]
- )
- )
- l
- )
- ) @
- [ CodePre "}" ]
in
let defs2 = (CodePre s_type3) :: defs in
let rec iter = function
@@ -634,11 +739,9 @@ class latex =
e :: (iter q)
in
(iter defs2) @
- [Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")] @
- (self#text_of_info t.ty_info)
+ (self#text_of_info te.te_info)
in
- self#latex_of_text fmt
- ((Latex (self#make_label (self#type_label t.ty_name))) :: text)
+ self#latex_of_text fmt text
(** Print LaTeX code for an exception. *)
method latex_of_exception fmt e =
@@ -1034,6 +1137,7 @@ class latex =
| Element_class c -> self#latex_of_class fmt c
| Element_class_type ct -> self#latex_of_class_type fmt ct
| Element_value v -> self#latex_of_value fmt v
+ | Element_type_extension te -> self#latex_of_type_extension module_name fmt te
| Element_exception e -> self#latex_of_exception fmt e
| Element_type t -> self#latex_of_type fmt t
| Element_module_comment t -> self#latex_of_text fmt t
diff --git a/ocamldoc/odoc_man.ml b/ocamldoc/odoc_man.ml
index 8a252d6311..def2377882 100644
--- a/ocamldoc/odoc_man.ml
+++ b/ocamldoc/odoc_man.ml
@@ -15,6 +15,7 @@ open Odoc_info
open Parameter
open Value
open Type
+open Extension
open Exception
open Class
open Module
@@ -281,8 +282,8 @@ class man =
Str.global_replace (Str.regexp "[ ]*\n[ ]*") " " s
(** Print the groff string for a text element. *)
- method man_of_text_element b te =
- match te with
+ method man_of_text_element b txt =
+ match txt with
| Odoc_info.Raw s -> bs b (self#escape s)
| Odoc_info.Code s ->
bs b "\n.B ";
@@ -421,6 +422,74 @@ class man =
self#man_of_info b v.val_info;
bs b "\n.sp\n"
+ (** Print groff string code for a type extension. *)
+ method man_of_type_extension b m_name te =
+ Odoc_info.reset_type_names () ;
+ bs b ".I type ";
+ (
+ match te.te_type_parameters with
+ [] -> ()
+ | l ->
+ let s = Odoc_str.string_of_type_extension_param_list te in
+ let s2 = Str.global_replace (Str.regexp "\n") "\n.B " s in
+ bs b "\n.B ";
+ bs b (self#relative_idents m_name s2);
+ bs b "\n";
+ bs b ".I "
+ );
+ bs b (self#relative_idents m_name te.te_type_name);
+ bs b " \n";
+ bs b "+=";
+ if te.te_private = Asttypes.Private then bs b " private";
+ bs b "\n ";
+ List.iter
+ (fun x ->
+ let father = Name.father x.xt_name in
+ bs b ("| "^(Name.simple x.xt_name));
+ (
+ match x.xt_args, x.xt_ret with
+ | [], None -> bs b "\n"
+ | l, None ->
+ bs b "\n.B of ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ | [], Some r ->
+ bs b "\n.B : ";
+ self#man_of_type_expr b father r;
+ | l, Some r ->
+ bs b "\n.B : ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ bs b ".B -> ";
+ self#man_of_type_expr b father r;
+ );
+ (
+ match x.xt_alias with
+ None -> ()
+ | Some xa ->
+ bs b ".B = ";
+ bs b
+ (
+ match xa.xa_xt with
+ None -> xa.xa_name
+ | Some x -> x.xt_name
+ );
+ bs b "\n"
+ );
+ (
+ match x.xt_text with
+ None ->
+ bs b " "
+ | Some t ->
+ bs b ".I \" \"\n";
+ bs b "(* ";
+ self#man_of_info b (Some t);
+ bs b " *)\n "
+ )
+ )
+ te.te_constructors;
+ bs b "\n.sp\n";
+ self#man_of_info b te.te_info;
+ bs b "\n.sp\n"
+
(** Print groff string code for an exception. *)
method man_of_exception b e =
Odoc_info.reset_type_names () ;
@@ -428,13 +497,23 @@ class man =
bs b (Name.simple e.ex_name);
bs b " \n";
(
- match e.ex_args with
- [] -> ()
- | _ ->
+ match e.ex_args, e.ex_ret with
+ | [], None -> ()
+ | l, None ->
bs b ".B of ";
self#man_of_type_expr_list
~par: false
b (Name.father e.ex_name) " * " e.ex_args
+ | [], Some r ->
+ bs b ".B : ";
+ self#man_of_type_expr b (Name.father e.ex_name) r
+ | l, Some r ->
+ bs b ".B : ";
+ self#man_of_type_expr_list
+ ~par: false
+ b (Name.father e.ex_name) " * " l;
+ bs b ".B -> ";
+ self#man_of_type_expr b (Name.father e.ex_name) r
);
(
match e.ex_alias with
@@ -456,6 +535,13 @@ class man =
method man_of_type b t =
Odoc_info.reset_type_names () ;
let father = Name.father t.ty_name in
+ let field_comment = function
+ | None -> ()
+ | Some t ->
+ bs b " (* ";
+ self#man_of_info b (Some t);
+ bs b " *) "
+ in
bs b ".I type ";
self#man_of_type_expr_param_list b father t;
(
@@ -469,7 +555,18 @@ class man =
(
match t.ty_manifest with
None -> ()
- | Some typ ->
+ | Some (Object_type l) ->
+ bs b "= ";
+ if priv then bs b "private ";
+ bs b "<";
+ List.iter (fun r ->
+ bs b (r.of_name^" : ");
+ self#man_of_type_expr b father r.of_type;
+ bs b ";";
+ field_comment r.of_text ;
+ ) l;
+ bs b "\n >\n"
+ | Some (Other typ) ->
bs b "= ";
if priv then bs b "private ";
self#man_of_type_expr b father typ
@@ -478,80 +575,68 @@ class man =
match t.ty_kind with
Type_abstract -> ()
| Type_variant l ->
- bs b "=";
- if priv then bs b " private";
- bs b "\n ";
- List.iter
- (fun constr ->
- bs b ("| "^constr.vc_name);
- (
- match constr.vc_args, constr.vc_text,constr.vc_ret with
- | [], None, None -> bs b "\n "
- | [], (Some t), None ->
- bs b " (*\n";
- self#man_of_info b (Some t);
- bs b "*)\n "
- | l, None, None ->
- bs b "\n.B of ";
- self#man_of_type_expr_list ~par: false b father " * " l;
- bs b " "
- | l, (Some t), None ->
- bs b "\n.B of ";
- self#man_of_type_expr_list ~par: false b father " * " l;
- bs b ".I \" \"\n";
- bs b "(*\n";
- self#man_of_info b (Some t);
- bs b "*)\n"
- | [], None, Some r ->
- bs b "\n.B : ";
- self#man_of_type_expr b father r;
- bs b " "
- | [], (Some t), Some r ->
- bs b "\n.B : ";
- self#man_of_type_expr b father r;
- bs b ".I \" \"\n";
- bs b "(*\n";
- self#man_of_info b (Some t);
- bs b "*)\n "
- | l, None, Some r ->
- bs b "\n.B : ";
- self#man_of_type_expr_list ~par: false b father " * " l;
- bs b ".B -> ";
- self#man_of_type_expr b father r;
- bs b " "
- | l, (Some t), Some r ->
- bs b "\n.B of ";
- self#man_of_type_expr_list ~par: false b father " * " l;
- bs b ".B -> ";
- self#man_of_type_expr b father r;
- bs b ".I \" \"\n";
- bs b "(*\n";
- self#man_of_info b (Some t);
- bs b "*)\n "
- )
- )
- l
+ bs b "=";
+ if priv then bs b " private";
+ bs b "\n ";
+ List.iter (fun constr ->
+ bs b ("| "^constr.vc_name);
+ let print_text t =
+ bs b " (* ";
+ self#man_of_info b (Some t);
+ bs b " *)\n "
+ in
+ match constr.vc_args, constr.vc_text,constr.vc_ret with
+ | [], None, None -> bs b "\n "
+ | [], (Some t), None ->
+ print_text t
+ | l, None, None ->
+ bs b "\n.B of ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ bs b " "
+ | l, (Some t), None ->
+ bs b "\n.B of ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ bs b ".I \" \"\n";
+ print_text t
+ | [], None, Some r ->
+ bs b "\n.B : ";
+ self#man_of_type_expr b father r;
+ bs b " "
+ | [], (Some t), Some r ->
+ bs b "\n.B : ";
+ self#man_of_type_expr b father r;
+ bs b ".I \" \"\n";
+ print_text t
+ | l, None, Some r ->
+ bs b "\n.B : ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ bs b ".B -> ";
+ self#man_of_type_expr b father r;
+ bs b " "
+ | l, (Some t), Some r ->
+ bs b "\n.B of ";
+ self#man_of_type_expr_list ~par: false b father " * " l;
+ bs b ".B -> ";
+ self#man_of_type_expr b father r;
+ bs b ".I \" \"\n";
+ print_text t
+ ) l
+
| Type_record l ->
bs b "= ";
if priv then bs b "private ";
bs b "{";
- List.iter
- (fun r ->
- bs b (if r.rf_mutable then "\n\n.B mutable \n" else "\n ");
- bs b (r.rf_name^" : ");
- self#man_of_type_expr b father r.rf_type;
- bs b ";";
- (
- match r.rf_text with
- None -> ()
- | Some t ->
- bs b " (*\n";
- self#man_of_info b (Some t);
- bs b "*) "
- );
- )
- l;
+ List.iter (fun r ->
+ bs b (if r.rf_mutable then "\n\n.B mutable \n" else "\n ");
+ bs b (r.rf_name^" : ");
+ self#man_of_type_expr b father r.rf_type;
+ bs b ";";
+ field_comment r.rf_text ;
+ ) l;
bs b "\n }\n"
+ | Type_open ->
+ bs b "= ..";
+ bs b "\n"
);
bs b "\n.sp\n";
self#man_of_info b t.ty_info;
@@ -724,6 +809,33 @@ class man =
self#man_of_text b [Code ("=== "^(Odoc_misc.string_of_text text)^" ===")];
bs b "\n.PP\n"
+ method man_of_recfield b modname f =
+ bs b ".I ";
+ if f.rf_mutable then bs b (Odoc_messages.mutab^" ");
+ bs b (f.rf_name^" : ");
+ self#man_of_type_expr b modname f.rf_type;
+ bs b "\n.sp\n";
+ self#man_of_info b f.rf_text;
+ bs b "\n.sp\n"
+
+ method man_of_const b modname c =
+ bs b ".I ";
+ bs b (c.vc_name^" ");
+ (match c.vc_args with
+ [] -> ()
+ | h::q ->
+ bs b "of ";
+ self#man_of_type_expr b modname h;
+ List.iter
+ (fun ty ->
+ bs b " * ";
+ self#man_of_type_expr b modname ty)
+ q
+ );
+ bs b "\n.sp\n";
+ self#man_of_info b c.vc_text;
+ bs b "\n.sp\n"
+
(** Print groff string for an included module. *)
method man_of_included_module b m_name im =
bs b ".I include ";
@@ -858,6 +970,42 @@ class man =
incr Odoc_info.errors ;
prerr_endline s
+ method man_of_module_type_body b mt =
+ self#man_of_info b mt.mt_info;
+ bs b "\n.sp\n";
+
+ (* parameters for functors *)
+ self#man_of_module_parameter_list b "" (Module.module_type_parameters mt);
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+
+ (* module elements *)
+ List.iter
+ (fun ele ->
+ match ele with
+ Element_module m ->
+ self#man_of_module b m
+ | Element_module_type mt ->
+ self#man_of_modtype b mt
+ | Element_included_module im ->
+ self#man_of_included_module b mt.mt_name im
+ | Element_class c ->
+ self#man_of_class b c
+ | Element_class_type ct ->
+ self#man_of_class_type b ct
+ | Element_value v ->
+ self#man_of_value b v
+ | Element_type_extension te ->
+ self#man_of_type_extension b mt.mt_name te
+ | Element_exception e ->
+ self#man_of_exception b e
+ | Element_type t ->
+ self#man_of_type b t
+ | Element_module_comment text ->
+ self#man_of_module_comment b text
+ )
+ (Module.module_type_elements mt);
+
(** Generate the man file for the given module type.
@raise Failure if an error occurs.*)
method generate_for_module_type mt =
@@ -895,38 +1043,7 @@ class man =
self#man_of_module_type b (Name.father mt.mt_name) t
);
bs b "\n.sp\n";
- self#man_of_info b mt.mt_info;
- bs b "\n.sp\n";
-
- (* parameters for functors *)
- self#man_of_module_parameter_list b "" (Module.module_type_parameters mt);
- (* a large blank *)
- bs b "\n.sp\n.sp\n";
-
- (* module elements *)
- List.iter
- (fun ele ->
- match ele with
- Element_module m ->
- self#man_of_module b m
- | Element_module_type mt ->
- self#man_of_modtype b mt
- | Element_included_module im ->
- self#man_of_included_module b mt.mt_name im
- | Element_class c ->
- self#man_of_class b c
- | Element_class_type ct ->
- self#man_of_class_type b ct
- | Element_value v ->
- self#man_of_value b v
- | Element_exception e ->
- self#man_of_exception b e
- | Element_type t ->
- self#man_of_type b t
- | Element_module_comment text ->
- self#man_of_module_comment b text
- )
- (Module.module_type_elements mt);
+ self#man_of_module_type_body b mt;
Buffer.output_buffer chanout b;
close_out chanout
@@ -936,6 +1053,42 @@ class man =
incr Odoc_info.errors ;
prerr_endline s
+ method man_of_module_body b m =
+ self#man_of_info b m.m_info;
+ bs b "\n.sp\n";
+
+ (* parameters for functors *)
+ self#man_of_module_parameter_list b "" (Module.module_parameters m);
+ (* a large blank *)
+ bs b "\n.sp\n.sp\n";
+
+ (* module elements *)
+ List.iter
+ (fun ele ->
+ match ele with
+ Element_module m ->
+ self#man_of_module b m
+ | Element_module_type mt ->
+ self#man_of_modtype b mt
+ | Element_included_module im ->
+ self#man_of_included_module b m.m_name im
+ | Element_class c ->
+ self#man_of_class b c
+ | Element_class_type ct ->
+ self#man_of_class_type b ct
+ | Element_value v ->
+ self#man_of_value b v
+ | Element_type_extension te ->
+ self#man_of_type_extension b m.m_name te
+ | Element_exception e ->
+ self#man_of_exception b e
+ | Element_type t ->
+ self#man_of_type b t
+ | Element_module_comment text ->
+ self#man_of_module_comment b text
+ )
+ (Module.module_elements m);
+
(** Generate the man file for the given module.
@raise Failure if an error occurs.*)
method generate_for_module m =
@@ -969,39 +1122,7 @@ class man =
bs b " : ";
self#man_of_module_type b (Name.father m.m_name) m.m_type;
bs b "\n.sp\n";
- self#man_of_info b m.m_info;
- bs b "\n.sp\n";
-
- (* parameters for functors *)
- self#man_of_module_parameter_list b "" (Module.module_parameters m);
- (* a large blank *)
- bs b "\n.sp\n.sp\n";
-
- (* module elements *)
- List.iter
- (fun ele ->
- match ele with
- Element_module m ->
- self#man_of_module b m
- | Element_module_type mt ->
- self#man_of_modtype b mt
- | Element_included_module im ->
- self#man_of_included_module b m.m_name im
- | Element_class c ->
- self#man_of_class b c
- | Element_class_type ct ->
- self#man_of_class_type b ct
- | Element_value v ->
- self#man_of_value b v
- | Element_exception e ->
- self#man_of_exception b e
- | Element_type t ->
- self#man_of_type b t
- | Element_module_comment text ->
- self#man_of_module_comment b text
- )
- (Module.module_elements m);
-
+ self#man_of_module_body b m;
Buffer.output_buffer chanout b;
close_out chanout
@@ -1010,7 +1131,7 @@ class man =
raise (Failure s)
(** Create the groups of elements to generate pages for. *)
- method create_groups module_list =
+ method create_groups mini module_list =
let name res_ele =
match res_ele with
Res_module m -> m.m_name
@@ -1019,6 +1140,7 @@ class man =
| Res_class_type ct -> ct.clt_name
| Res_value v -> Name.simple v.val_name
| Res_type t -> Name.simple t.ty_name
+ | Res_extension x -> Name.simple x.xt_name
| Res_exception e -> Name.simple e.ex_name
| Res_attribute a -> Name.simple a.att_value.val_name
| Res_method m -> Name.simple m.met_value.val_name
@@ -1028,7 +1150,13 @@ class man =
in
let all_items_pre = Odoc_info.Search.search_by_name module_list (Str.regexp ".*") in
let all_items = List.filter
- (fun r -> match r with Res_section _ -> false | _ -> true)
+ (fun r ->
+ match r with
+ Res_section _ -> false
+ | Res_module _ | Res_module_type _
+ | Res_class _ | Res_class_type _ -> true
+ | _ -> not mini
+ )
all_items_pre
in
let sorted_items = List.sort (fun e1 -> fun e2 -> compare (name e1) (name e2)) all_items in
@@ -1062,6 +1190,7 @@ class man =
| Res_class_type ct -> ct.clt_name
| Res_value v -> v.val_name
| Res_type t -> t.ty_name
+ | Res_extension x -> x.xt_name
| Res_exception e -> e.ex_name
| Res_attribute a -> a.att_value.val_name
| Res_method m -> m.met_value.val_name
@@ -1091,6 +1220,9 @@ class man =
| Res_type t ->
bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father t.ty_name)^"\n");
self#man_of_type b t
+ | Res_extension x ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father x.xt_name)^"\n");
+ self#man_of_type_extension b (Name.father x.xt_name) x.xt_type_extension
| Res_exception e ->
bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father e.ex_name)^"\n");
self#man_of_exception b e
@@ -1106,7 +1238,45 @@ class man =
| Res_class_type ct ->
bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father ct.clt_name)^"\n");
self#man_of_class_type b ct
- | _ ->
+ | Res_recfield (ty,f) ->
+ bs b ("\n.SH Type "^(ty.ty_name)^"\n");
+ self#man_of_recfield b (Name.father ty.ty_name) f
+ | Res_const (ty,c) ->
+ bs b ("\n.SH Type "^(ty.ty_name)^"\n");
+ self#man_of_const b (Name.father ty.ty_name) c
+ | Res_module m ->
+ if Name.father m.m_name <> "" then
+ begin
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father m.m_name)^"\n");
+ bs b (Odoc_messages.modul^"\n");
+ bs b (".BI \""^(Name.simple m.m_name)^"\"\n");
+ bs b " : ";
+ self#man_of_module_type b (Name.father m.m_name) m.m_type;
+ end
+ else
+ begin
+ bs b ("\n.SH "^Odoc_messages.modul^" "^m.m_name^"\n");
+ bs b " : ";
+ self#man_of_module_type b (Name.father m.m_name) m.m_type;
+ end;
+ bs b "\n.sp\n";
+ self#man_of_module_body b m
+
+ | Res_module_type mt ->
+ bs b ("\n.SH "^Odoc_messages.modul^" "^(Name.father mt.mt_name)^"\n");
+ bs b (Odoc_messages.module_type^"\n");
+ bs b (".BI \""^(Name.simple mt.mt_name)^"\"\n");
+ bs b " = ";
+ (
+ match mt.mt_type with
+ None -> ()
+ | Some t ->
+ self#man_of_module_type b (Name.father mt.mt_name) t
+ );
+ bs b "\n.sp\n";
+ self#man_of_module_type_body b mt
+
+ | Res_section _ ->
(* normalement on ne peut pas avoir de module ici. *)
()
in
@@ -1121,7 +1291,7 @@ class man =
(** Generate all the man pages from a module list. *)
method generate module_list =
let sorted_module_list = Sort.list (fun m1 -> fun m2 -> m1.m_name < m2.m_name) module_list in
- let groups = self#create_groups sorted_module_list in
+ let groups = self#create_groups !man_mini sorted_module_list in
let f group =
match group with
[] ->
@@ -1130,11 +1300,7 @@ class man =
| [Res_module_type mt] -> self#generate_for_module_type mt
| [Res_class cl] -> self#generate_for_class cl
| [Res_class_type ct] -> self#generate_for_class_type ct
- | l ->
- if !man_mini then
- ()
- else
- self#generate_for_group l
+ | l -> self#generate_for_group l
in
List.iter f groups
end
diff --git a/ocamldoc/odoc_merge.ml b/ocamldoc/odoc_merge.ml
index eda6491ec9..443cc3d8a5 100644
--- a/ocamldoc/odoc_merge.ml
+++ b/ocamldoc/odoc_merge.ml
@@ -18,6 +18,7 @@ module Name = Odoc_name
open Odoc_parameter
open Odoc_value
open Odoc_type
+open Odoc_extension
open Odoc_exception
open Odoc_class
open Odoc_module
@@ -287,12 +288,41 @@ let merge_types merge_options mli ml =
in
List.iter f l1
+ | Type_open, Type_open ->
+ ()
+
| _ ->
if !Odoc_global.inverse_merge_ml_mli then
()
else
raise (Failure (Odoc_messages.different_types mli.ty_name))
+(** merge of two t_type_extension, one for a .mli, another for the .ml.
+ The .mli type is completed with the information in the .ml type.
+ Information for the extension constructors is merged separately
+ by [merge_extension_constructor]. *)
+let merge_type_extension merge_options mli ml =
+ mli.te_info <- merge_info_opt merge_options mli.te_info ml.te_info;
+ mli.te_loc <- { mli.te_loc with loc_impl = ml.te_loc.loc_impl } ;
+ mli.te_code <- (match mli.te_code with None -> ml.te_code | _ -> mli.te_code)
+
+(** merge of two t_extension_constructor, one for a .mli, another for the .ml.
+ The .mli type is completed with the information in the .ml type. *)
+let merge_extension_constructor merge_options mli ml =
+ let new_desc =
+ match mli.xt_text, ml.xt_text with
+ None, None -> None
+ | Some d, None
+ | None, Some d -> Some d
+ | Some d1, Some d2 ->
+ if List.mem Merge_description merge_options then
+ Some (merge_info merge_options d1 d2)
+ else
+ Some d1
+ in
+ mli.xt_text <- new_desc
+
+
(** Merge of two param_info, one from a .mli, one from a .ml.
The text fields are not handled but will be recreated from the
i_params field of the info structure.
@@ -498,6 +528,33 @@ let merge_class_types merge_options mli ml =
let rec merge_module_types merge_options mli ml =
mli.mt_info <- merge_info_opt merge_options mli.mt_info ml.mt_info;
mli.mt_loc <- { mli.mt_loc with loc_impl = ml.mt_loc.loc_impl } ;
+ (* merge type extensions *)
+ List.iter
+ (fun te ->
+ let rec f exts elems =
+ match exts, elems with
+ [], _
+ | _, [] -> ()
+ | _, (Element_type_extension te2 :: rest) ->
+ let merge_ext xt =
+ try
+ let xt2 =
+ List.find (fun xt2 -> xt.xt_name = xt2.xt_name)
+ te2.te_constructors
+ in
+ merge_extension_constructor merge_options xt xt2;
+ true
+ with Not_found -> false
+ in
+ let merged, unmerged = List.partition merge_ext exts in
+ if merged <> [] then merge_type_extension merge_options te te2;
+ f unmerged rest
+ | _, (_ :: rest) -> f exts rest
+ in
+ (* we look for the extensions in reverse order *)
+ f te.te_constructors (List.rev (Odoc_module.module_type_elements ml))
+ )
+ (Odoc_module.module_type_type_extensions mli);
(* merge exceptions *)
List.iter
(fun ex ->
@@ -746,6 +803,33 @@ and merge_modules merge_options mli ml =
mli.m_code <- code;
mli.m_code_intf <- code_intf;
+ (* merge type extensions *)
+ List.iter
+ (fun te ->
+ let rec f exts elems =
+ match exts, elems with
+ [], _
+ | _, [] -> ()
+ | _, (Element_type_extension te2 :: rest) ->
+ let merge_ext xt =
+ try
+ let xt2 =
+ List.find (fun xt2 -> xt.xt_name = xt2.xt_name)
+ te2.te_constructors
+ in
+ merge_extension_constructor merge_options xt xt2;
+ true
+ with Not_found -> false
+ in
+ let merged, unmerged = List.partition merge_ext exts in
+ if merged <> [] then merge_type_extension merge_options te te2;
+ f unmerged rest
+ | _, (_ :: rest) -> f exts rest
+ in
+ (* we look for the extensions in reverse order *)
+ f te.te_constructors (List.rev (Odoc_module.module_elements ml))
+ )
+ (Odoc_module.module_type_extensions mli);
(* merge exceptions *)
List.iter
(fun ex ->
diff --git a/ocamldoc/odoc_messages.ml b/ocamldoc/odoc_messages.ml
index 2d6327bba7..4c409a3a17 100644
--- a/ocamldoc/odoc_messages.ml
+++ b/ocamldoc/odoc_messages.ml
@@ -132,6 +132,11 @@ let latex_type_elt_prefix =
"<string>\n\t\tUse <string> as prefix for the LaTeX labels of type elements.\n"^
"\t\t(default is \""^default_latex_type_elt_prefix^"\")"
+let default_latex_extension_prefix = "extension:"
+let latex_extension_prefix =
+ "<string>\n\t\tUse <string> as prefix for the LaTeX labels of extensions.\n"^
+ "\t\t(default is \""^default_latex_extension_prefix^"\")"
+
let default_latex_exception_prefix = "exception:"
let latex_exception_prefix =
"<string>\n\t\tUse <string> as prefix for the LaTeX labels of exceptions.\n"^
@@ -258,6 +263,7 @@ let unknown_extension f = "Unknown extension for file "^f^"."
let two_implementations name = "There are two implementations of module "^name^"."
let two_interfaces name = "There are two interfaces of module "^name^"."
let too_many_module_objects name = "There are too many interfaces/implementation of module "^name^"."
+let extension_not_found_in_implementation ext m = "Extension "^ext^" was not found in implementation of module "^m^"."
let exception_not_found_in_implementation exc m = "Exception "^exc^" was not found in implementation of module "^m^"."
let type_not_found_in_implementation exc m = "Type "^exc^" was not found in implementation of module "^m^"."
let module_not_found_in_implementation m m2 = "Module "^m^" was not found in implementation of module "^m2^"."
@@ -271,11 +277,13 @@ let method_type_not_found cl met = "The type of the method "^met^" could not be
let module_not_found m m2 = "The module "^m2^" could not be found in the signature of module "^m^"."
let module_type_not_found m mt = "The module type "^mt^" could not be found in the signature of module "^m^"."
let value_not_found m v = "The value "^v^" could not be found in the signature of module "^m^"."
+let extension_not_found m e = "The extension "^e^" could not be found in the signature of module "^m^"."
let exception_not_found m e = "The exception "^e^" could not be found in the signature of module "^m^"."
let type_not_found m t = "The type "^t^" could not be found in the signature of module "^m^"."
let class_not_found m c = "The class "^c^" could not be found in the signature of module "^m^"."
let class_type_not_found m c = "The class type "^c^" could not be found in the signature of module "^m^"."
let type_not_found_in_typedtree t = "Type "^t^" was not found in typed tree."
+let extension_not_found_in_typedtree x = "Extension "^x^" was not found in typed tree."
let exception_not_found_in_typedtree e = "Exception "^e^" was not found in typed tree."
let module_type_not_found_in_typedtree mt = "Module type "^mt^" was not found in typed tree."
let module_not_found_in_typedtree m = "Module "^m^" was not found in typed tree."
@@ -293,6 +301,7 @@ let cross_module_or_module_type_not_found n = "Module or module type "^n^" not f
let cross_class_not_found n = "Class "^n^" not found"
let cross_class_type_not_found n = "class type "^n^" not found"
let cross_class_or_class_type_not_found n = "Class or class type "^n^" not found"
+let cross_extension_not_found n = "Extension "^n^" not found"
let cross_exception_not_found n = "Exception "^n^" not found"
let cross_element_not_found n = "Element "^n^" not found"
let cross_method_not_found n = "Method "^n^" not found"
@@ -329,6 +338,7 @@ let modules = "Modules"
let functors = "Functors"
let values = "Simple values"
let types = "Types"
+let extensions = "Extensions"
let exceptions = "Exceptions"
let record = "Record"
let variant = "Variant"
@@ -363,6 +373,7 @@ let documentation = "Documentation"
let index_of = "Index of"
let top = "Top"
let index_of_values = index_of^" values"
+let index_of_extensions = index_of^" extensions"
let index_of_exceptions = index_of^" exceptions"
let index_of_types = index_of^" types"
let index_of_attributes = index_of^" class attributes"
diff --git a/ocamldoc/odoc_misc.ml b/ocamldoc/odoc_misc.ml
index c762ade2a4..e938dbe679 100644
--- a/ocamldoc/odoc_misc.ml
+++ b/ocamldoc/odoc_misc.ml
@@ -23,7 +23,7 @@ let no_blanks s =
let input_file_as_string nom =
let chanin = open_in_bin nom in
let len = 1024 in
- let s = String.create len in
+ let s = Bytes.create len in
let buf = Buffer.create len in
let rec iter () =
try
@@ -32,7 +32,7 @@ let input_file_as_string nom =
()
else
(
- Buffer.add_substring buf s 0 n;
+ Buffer.add_subbytes buf s 0 n;
iter ()
)
with
@@ -313,8 +313,8 @@ let get_titles_in_text t =
| Odoc_types.Index_list -> ()
| Odoc_types.Custom (_, t) -> iter_text t
| Odoc_types.Target _ -> ()
- and iter_text te =
- List.iter iter_ele te
+ and iter_text txt =
+ List.iter iter_ele txt
in
iter_text t;
List.rev !l
diff --git a/ocamldoc/odoc_module.ml b/ocamldoc/odoc_module.ml
index b1bedfa77f..9ed2b17717 100644
--- a/ocamldoc/odoc_module.ml
+++ b/ocamldoc/odoc_module.ml
@@ -24,6 +24,7 @@ type module_element =
| Element_class of Odoc_class.t_class
| Element_class_type of Odoc_class.t_class_type
| Element_value of Odoc_value.t_value
+ | Element_type_extension of Odoc_extension.t_type_extension
| Element_exception of Odoc_exception.t_exception
| Element_type of Odoc_type.t_type
| Element_module_comment of Odoc_types.text
@@ -127,6 +128,17 @@ let types l =
[]
l
+(** Returns the list of type extensions from a list of module_element. *)
+let type_extensions l =
+ List.fold_left
+ (fun acc -> fun ele ->
+ match ele with
+ Element_type_extension x -> acc @ [x]
+ | _ -> acc
+ )
+ []
+ l
+
(** Returns the list of exceptions from a list of module_element. *)
let exceptions l =
List.fold_left
@@ -301,7 +313,11 @@ let module_simple_values ?(trans=true) m =
@param trans indicates if, for aliased modules, we must perform a transitive search.*)
let module_types ?(trans=true) m = types (module_elements ~trans m)
-(** Returns the list of excptions of a module.
+(** Returns the list of type extensions of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_extensions ?(trans=true) m = type_extensions (module_elements ~trans m)
+
+(** Returns the list of exceptions of a module.
@param trans indicates if, for aliased modules, we must perform a transitive search.*)
let module_exceptions ?(trans=true) m = exceptions (module_elements ~trans m)
@@ -463,7 +479,11 @@ let module_type_values ?(trans=true) m = values (module_type_elements ~trans m)
@param trans indicates if, for aliased modules, we must perform a transitive search.*)
let module_type_types ?(trans=true) m = types (module_type_elements ~trans m)
-(** Returns the list of excptions of a module.
+(** Returns the list of type extensions of a module.
+ @param trans indicates if, for aliased modules, we must perform a transitive search.*)
+let module_type_type_extensions ?(trans=true) m = type_extensions (module_type_elements ~trans m)
+
+(** Returns the list of exceptions of a module.
@param trans indicates if, for aliased modules, we must perform a transitive search.*)
let module_type_exceptions ?(trans=true) m = exceptions (module_type_elements ~trans m)
diff --git a/ocamldoc/odoc_scan.ml b/ocamldoc/odoc_scan.ml
index e507c48b7e..e6c19f29d4 100644
--- a/ocamldoc/odoc_scan.ml
+++ b/ocamldoc/odoc_scan.ml
@@ -38,12 +38,32 @@ class scanner =
Odoc_type.Type_abstract -> ()
| Odoc_type.Type_variant l -> List.iter (self#scan_type_const t) l
| Odoc_type.Type_record l -> List.iter (self#scan_type_recfield t) l
+ | Odoc_type.Type_open -> ()
+ method scan_extension_constructor (e : Odoc_extension.t_extension_constructor) = ()
method scan_exception (e : Odoc_exception.t_exception) = ()
method scan_attribute (a : Odoc_value.t_attribute) = ()
method scan_method (m : Odoc_value.t_method) = ()
method scan_included_module (im : Odoc_module.included_module) = ()
+ (** Scan of a type extension *)
+
+ (** Overide this method to perform controls on the extension's type,
+ private and info. This method is called before scanning the
+ extensions's constructors.
+ @return true if the extension's constructors must be scanned.*)
+ method scan_type_extension_pre (x: Odoc_extension.t_type_extension) = true
+
+ (** This method scans the constructors of the given type extension. *)
+ method scan_type_extension_constructors (x: Odoc_extension.t_type_extension) =
+ List.iter self#scan_extension_constructor (Odoc_extension.extension_constructors x)
+
+ (** Scan of a type extension. Should not be overridden. It calls [scan_type_extension_pre]
+ and if [scan_type_extension_pre] returns [true], then it calls scan_type_extension_constructors.*)
+ method scan_type_extension (x: Odoc_extension.t_type_extension) =
+ if self#scan_type_extension_pre x then self#scan_type_extension_constructors x
+
+
(** Scan of a class. *)
(** Scan of a comment inside a class. *)
@@ -117,6 +137,7 @@ class scanner =
| Odoc_module.Element_class c -> self#scan_class c
| Odoc_module.Element_class_type ct -> self#scan_class_type ct
| Odoc_module.Element_value v -> self#scan_value v
+ | Odoc_module.Element_type_extension x -> self#scan_type_extension x
| Odoc_module.Element_exception e -> self#scan_exception e
| Odoc_module.Element_type t -> self#scan_type t
| Odoc_module.Element_module_comment t -> self#scan_module_comment t
@@ -148,6 +169,7 @@ class scanner =
| Odoc_module.Element_class c -> self#scan_class c
| Odoc_module.Element_class_type ct -> self#scan_class_type ct
| Odoc_module.Element_value v -> self#scan_value v
+ | Odoc_module.Element_type_extension x -> self#scan_type_extension x
| Odoc_module.Element_exception e -> self#scan_exception e
| Odoc_module.Element_type t -> self#scan_type t
| Odoc_module.Element_module_comment t -> self#scan_module_comment t
diff --git a/ocamldoc/odoc_search.ml b/ocamldoc/odoc_search.ml
index 4e76d9fe49..763b71602d 100644
--- a/ocamldoc/odoc_search.ml
+++ b/ocamldoc/odoc_search.ml
@@ -16,6 +16,7 @@ module Name = Odoc_name
open Odoc_parameter
open Odoc_value
open Odoc_type
+open Odoc_extension
open Odoc_exception
open Odoc_class
open Odoc_module
@@ -27,6 +28,7 @@ type result_element =
| Res_class_type of t_class_type
| Res_value of t_value
| Res_type of t_type
+ | Res_extension of t_extension_constructor
| Res_exception of t_exception
| Res_attribute of t_attribute
| Res_method of t_method
@@ -47,6 +49,7 @@ module type Predicates =
val p_recfield : t_type -> record_field -> t -> bool
val p_const : t_type -> variant_constructor -> t -> bool
val p_type : t_type -> t -> (bool * bool)
+ val p_extension : t_extension_constructor -> t -> bool
val p_exception : t_exception -> t -> bool
val p_attribute : t_attribute -> t -> bool
val p_method : t_method -> t -> bool
@@ -113,9 +116,19 @@ module Search =
List.flatten (List.map (fun rf -> search_recfield t rf v) l)
| Type_variant l ->
List.flatten (List.map (fun rf -> search_const t rf v) l)
+ | Type_open -> []
in
if ok then (Res_type t) :: l else l
+ let search_extension_constructor xt v =
+ if P.p_extension xt v then [Res_extension xt] else []
+
+ let search_type_extension te v =
+ List.fold_left
+ (fun acc -> fun xt -> acc @ (search_extension_constructor xt v))
+ []
+ (Odoc_extension.extension_constructors te)
+
let search_exception e v = if P.p_exception e v then [Res_exception e] else []
let search_attribute a v = if P.p_attribute a v then [Res_attribute a] else []
@@ -202,6 +215,12 @@ module Search =
[]
(Odoc_module.module_type_types mt)
in
+ let res_ext =
+ List.fold_left
+ (fun acc -> fun te -> acc @ (search_type_extension te v))
+ []
+ (Odoc_module.module_type_type_extensions mt)
+ in
let res_exc =
List.fold_left
(fun acc -> fun e -> acc @ (search_exception e v))
@@ -233,7 +252,7 @@ module Search =
[]
(Odoc_module.module_type_comments mt)
in
- let l = res_val @ res_typ @ res_exc @ res_mod @
+ let l = res_val @ res_typ @ res_ext @ res_exc @ res_mod @
res_modtyp @ res_cl @ res_cltyp @ res_sec
in
l
@@ -261,6 +280,12 @@ module Search =
[]
(Odoc_module.module_types m)
in
+ let res_ext =
+ List.fold_left
+ (fun acc -> fun te -> acc @ (search_type_extension te v))
+ []
+ (Odoc_module.module_type_extensions m)
+ in
let res_exc =
List.fold_left
(fun acc -> fun e -> acc @ (search_exception e v))
@@ -292,7 +317,7 @@ module Search =
[]
(Odoc_module.module_comments m)
in
- let l = res_val @ res_typ @ res_exc @ res_mod @
+ let l = res_val @ res_typ @ res_ext @ res_exc @ res_mod @
res_modtyp @ res_cl @ res_cltyp @ res_sec
in
l
@@ -334,6 +359,7 @@ module P_name =
let name = Printf.sprintf "%s.%s" t.ty_name f.vc_name in
name =~ r
let p_type t r = (true, t.ty_name =~ r)
+ let p_extension x r = x.xt_name =~ r
let p_exception e r = e.ex_name =~ r
let p_attribute a r = a.att_value.val_name =~ r
let p_method m r = m.met_value.val_name =~ r
@@ -353,6 +379,7 @@ module P_values =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type _ _ = (false, false)
+ let p_extension _ _ = false
let p_exception _ _ = false
let p_attribute _ _ = false
let p_method _ _ = false
@@ -369,6 +396,34 @@ let values l =
in
iter [] l_ele
+module P_extensions =
+ struct
+ type t = unit
+ let p_module _ _ = (true, false)
+ let p_module_type _ _ = (true, false)
+ let p_class _ _ = (false, false)
+ let p_class_type _ _ = (false, false)
+ let p_value _ _ = false
+ let p_recfield _ _ _ = false
+ let p_const _ _ _ = false
+ let p_type _ _ = (false, false)
+ let p_extension _ _ = true
+ let p_exception _ _ = false
+ let p_attribute _ _ = false
+ let p_method _ _ = false
+ let p_section _ _ = false
+ end
+module Search_extensions = Search ( P_extensions )
+let extensions l =
+ let l_ele = Search_extensions.search l () in
+ let p x1 x2 = x1.xt_name = x2.xt_name in
+ let rec iter acc = function
+ (Res_extension x) :: q -> if List.exists (p x) acc then iter acc q else iter (x :: acc) q
+ | _ :: q -> iter acc q
+ | [] -> acc
+ in
+ iter [] l_ele
+
module P_exceptions =
struct
type t = unit
@@ -380,6 +435,7 @@ module P_exceptions =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type _ _ = (false, false)
+ let p_extension _ _ = false
let p_exception _ _ = true
let p_attribute _ _ = false
let p_method _ _ = false
@@ -407,6 +463,7 @@ module P_types =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type _ _ = (false, true)
+ let p_extension _ _ = false
let p_exception _ _ = false
let p_attribute _ _ = false
let p_method _ _ = false
@@ -434,6 +491,7 @@ module P_attributes =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type _ _ = (false, false)
+ let p_extension _ _ = false
let p_exception _ _ = false
let p_attribute _ _ = true
let p_method _ _ = false
@@ -461,6 +519,7 @@ module P_methods =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type _ _ = (false, false)
+ let p_extension _ _ = false
let p_exception _ _ = false
let p_attribute _ _ = false
let p_method _ _ = true
@@ -488,6 +547,7 @@ module P_classes =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type _ _ = (false, false)
+ let p_extension _ _ = false
let p_exception _ _ = false
let p_attribute _ _ = false
let p_method _ _ = false
@@ -515,6 +575,7 @@ module P_class_types =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type _ _ = (false, false)
+ let p_extension _ _ = false
let p_exception _ _ = false
let p_attribute _ _ = false
let p_method _ _ = false
@@ -542,6 +603,7 @@ module P_modules =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type _ _ = (false, false)
+ let p_extension _ _ = false
let p_exception _ _ = false
let p_attribute _ _ = false
let p_method _ _ = false
@@ -569,6 +631,7 @@ module P_module_types =
let p_recfield _ _ _ = false
let p_const _ _ _ = false
let p_type _ _ = (false, false)
+ let p_extension _ _ = false
let p_exception _ _ = false
let p_attribute _ _ = false
let p_method _ _ = false
@@ -639,6 +702,15 @@ let module_type_exists mods regexp =
)
l
+let extension_exists mods regexp =
+ let l = Search_by_name.search mods regexp in
+ List.exists
+ (function
+ Res_extension _ -> true
+ | _ -> false
+ )
+ l
+
let exception_exists mods regexp =
let l = Search_by_name.search mods regexp in
List.exists
diff --git a/ocamldoc/odoc_search.mli b/ocamldoc/odoc_search.mli
index bd101aa558..e0d9f2c27a 100644
--- a/ocamldoc/odoc_search.mli
+++ b/ocamldoc/odoc_search.mli
@@ -20,6 +20,7 @@ type result_element =
| Res_class_type of Odoc_class.t_class_type
| Res_value of Odoc_value.t_value
| Res_type of Odoc_type.t_type
+ | Res_extension of Odoc_extension.t_extension_constructor
| Res_exception of Odoc_exception.t_exception
| Res_attribute of Odoc_value.t_attribute
| Res_method of Odoc_value.t_method
@@ -46,6 +47,8 @@ module type Predicates =
val p_recfield : Odoc_type.t_type -> Odoc_type.record_field -> t -> bool
val p_const : Odoc_type.t_type -> Odoc_type.variant_constructor -> t -> bool
val p_type : Odoc_type.t_type -> t -> (bool * bool)
+ val p_extension :
+ Odoc_extension.t_extension_constructor -> t -> bool
val p_exception : Odoc_exception.t_exception -> t -> bool
val p_attribute : Odoc_value.t_attribute -> t -> bool
val p_method : Odoc_value.t_method -> t -> bool
@@ -73,6 +76,14 @@ module Search :
(** search in a type *)
val search_type : Odoc_type.t_type -> P.t -> result_element list
+ (** search in an extension constructor *)
+ val search_extension_constructor :
+ Odoc_extension.t_extension_constructor -> P.t -> result_element list
+
+ (** search in a type extension *)
+ val search_type_extension :
+ Odoc_extension.t_type_extension -> P.t -> result_element list
+
(** search in an exception *)
val search_exception :
Odoc_exception.t_exception -> P.t -> result_element list
@@ -116,6 +127,8 @@ module P_name :
val p_recfield : Odoc_type.t_type -> Odoc_type.record_field -> Str.regexp -> bool
val p_const : Odoc_type.t_type -> Odoc_type.variant_constructor -> Str.regexp -> bool
val p_type : Odoc_type.t_type -> Str.regexp -> (bool * bool)
+ val p_extension :
+ Odoc_extension.t_extension_constructor -> Str.regexp -> bool
val p_exception : Odoc_exception.t_exception -> Str.regexp -> bool
val p_attribute : Odoc_value.t_attribute -> Str.regexp -> bool
val p_method : Odoc_value.t_method -> Str.regexp -> bool
@@ -129,6 +142,10 @@ module Search_by_name :
val search_recfield : Odoc_type.t_type -> Odoc_type.record_field -> P_name.t -> result_element list
val search_const : Odoc_type.t_type -> Odoc_type.variant_constructor -> P_name.t -> result_element list
val search_type : Odoc_type.t_type -> P_name.t -> result_element list
+ val search_extension_constructor :
+ Odoc_extension.t_extension_constructor -> P_name.t -> result_element list
+ val search_type_extension :
+ Odoc_extension.t_type_extension -> P_name.t -> result_element list
val search_exception :
Odoc_exception.t_exception -> P_name.t -> result_element list
val search_attribute :
@@ -148,6 +165,10 @@ module Search_by_name :
(** A function to search all the values in a list of modules. *)
val values : Odoc_module.t_module list -> Odoc_value.t_value list
+(** A function to search all the extension constructors in a list of modules. *)
+val extensions :
+ Odoc_module.t_module list -> Odoc_extension.t_extension_constructor list
+
(** A function to search all the exceptions in a list of modules. *)
val exceptions : Odoc_module.t_module list -> Odoc_exception.t_exception list
@@ -196,6 +217,10 @@ val class_exists : Odoc_module.t_module list -> Str.regexp -> bool
in the given module list.*)
val class_type_exists : Odoc_module.t_module list -> Str.regexp -> bool
+(** Return [true] if an extension with the given complete name (regexp) exists
+ in the given module list.*)
+val extension_exists : Odoc_module.t_module list -> Str.regexp -> bool
+
(** Return [true] if a exception with the given complete name (regexp) exists
in the given module list.*)
val exception_exists : Odoc_module.t_module list -> Str.regexp -> bool
diff --git a/ocamldoc/odoc_sig.ml b/ocamldoc/odoc_sig.ml
index 13b2503157..48fe8cd7f4 100644
--- a/ocamldoc/odoc_sig.ml
+++ b/ocamldoc/odoc_sig.ml
@@ -24,6 +24,7 @@ module Name = Odoc_name
open Odoc_parameter
open Odoc_value
open Odoc_type
+open Odoc_extension
open Odoc_exception
open Odoc_class
open Odoc_module
@@ -38,8 +39,7 @@ module Signature_search =
| T of string
| C of string
| CT of string
- | E of string
- | ER of string
+ | X of string
| P of string
type tab = (ele, Types.signature_item) Hashtbl.t
@@ -48,8 +48,8 @@ module Signature_search =
match signat with
Types.Sig_value (ident, _) ->
Hashtbl.add table (V (Name.from_ident ident)) signat
- | Types.Sig_exception (ident, _) ->
- Hashtbl.add table (E (Name.from_ident ident)) signat
+ | Types.Sig_typext (ident, _, _) ->
+ Hashtbl.add table (X (Name.from_ident ident)) signat
| Types.Sig_type (ident, _, _) ->
Hashtbl.add table (T (Name.from_ident ident)) signat
| Types.Sig_class (ident, _, _) ->
@@ -71,10 +71,9 @@ module Signature_search =
| (Types.Sig_value (_, val_desc)) -> val_desc.Types.val_type
| _ -> assert false
- let search_exception table name =
- match Hashtbl.find table (E name) with
- | (Types.Sig_exception (_, type_expr_list)) ->
- type_expr_list
+ let search_extension table name =
+ match Hashtbl.find table (X name) with
+ | (Types.Sig_typext (_, ext, _)) -> ext
| _ -> assert false
let search_type table name =
@@ -169,10 +168,44 @@ module Analyser =
let merge_infos = Odoc_merge.merge_info_opt Odoc_types.all_merge_options
- let name_comment_from_type_kind pos_end pos_limit tk =
- match tk with
- Parsetree.Ptype_abstract ->
- (0, [])
+ let name_comment_from_type_decl pos_end pos_limit ty_decl =
+ match ty_decl.Parsetree.ptype_kind with
+ | Parsetree.Ptype_abstract ->
+ let open Parsetree in
+ begin match ty_decl.ptype_manifest with
+ | None -> (0, [])
+ | Some core_ty ->
+ begin match core_ty.ptyp_desc with
+ | Ptyp_object (fields, _) ->
+ let rec f = function
+ | [] -> []
+ | ("",_,_) :: _ ->
+ (* Fields with no name have been eliminated previously. *)
+ assert false
+
+ | (name, _atts, ct) :: [] ->
+ let pos = ct.Parsetree.ptyp_loc.Location.loc_end.Lexing.pos_cnum in
+ let s = get_string_of_file pos pos_end in
+ let (_,comment_opt) = My_ir.just_after_special !file_name s in
+ [name, comment_opt]
+ | (name, _atts, ct) :: ((name2, _atts2, ct2) as ele2) :: q ->
+ let pos = ct.Parsetree.ptyp_loc.Location.loc_end.Lexing.pos_cnum in
+ let pos2 = ct2.Parsetree.ptyp_loc.Location.loc_start.Lexing.pos_cnum in
+ let s = get_string_of_file pos pos2 in
+ let (_,comment_opt) = My_ir.just_after_special !file_name s in
+ (name, comment_opt) :: (f (ele2 :: q))
+ in
+ let is_named_field field =
+ match field with
+ | ("",_,_) -> false
+ | _ -> true
+ in
+ (0, f @@ List.filter is_named_field fields)
+
+ | _ -> (0, [])
+ end
+ end
+
| Parsetree.Ptype_variant cons_core_type_list_list ->
let rec f acc cons_core_type_list_list =
let open Parsetree in
@@ -213,6 +246,25 @@ module Analyser =
(name.txt, comment_opt) :: (f (ele2 :: q))
in
(0, f name_mutable_type_list)
+ | Parsetree.Ptype_open ->
+ (0, [])
+
+
+ let manifest_structure env name_comment_list type_expr =
+ match type_expr.desc with
+ | Tobject (fields, _) ->
+ let f (field_name, _, type_expr) =
+ let comment_opt =
+ try List.assoc field_name name_comment_list
+ with Not_found -> None
+ in {
+ of_name = field_name ;
+ of_type = Odoc_env.subst_type env type_expr ;
+ of_text = comment_opt ;
+ }
+ in
+ Object_type (List.map f @@ fst @@ Ctype.flatten_fields fields)
+ | _ -> Other (Odoc_env.subst_type env type_expr)
let get_type_kind env name_comment_list type_kind =
match type_kind with
@@ -222,7 +274,7 @@ module Analyser =
let f {Types.cd_id=constructor_name;cd_args=type_expr_list;cd_res=ret_type} =
let constructor_name = Ident.name constructor_name in
let comment_opt =
- try List.assoc constructor_name name_comment_list
+ try List.assoc constructor_name name_comment_list
with Not_found -> None
in
{
@@ -250,6 +302,10 @@ module Analyser =
in
Odoc_type.Type_record (List.map f l)
+ | Types.Type_open ->
+ Odoc_type.Type_open
+
+
let erased_names_of_constraints constraints acc =
List.fold_right (fun constraint_ acc ->
match constraint_ with
@@ -267,6 +323,7 @@ module Analyser =
| Parsetree.Psig_attribute _
| Parsetree.Psig_extension _
| Parsetree.Psig_value _
+ | Parsetree.Psig_typext _
| Parsetree.Psig_exception _
| Parsetree.Psig_open _
| Parsetree.Psig_include _
@@ -297,7 +354,8 @@ module Analyser =
match ele2.Parsetree.pctf_desc with
Parsetree.Pctf_val (_, _, _, _)
| Parsetree.Pctf_method (_, _, _, _)
- | Parsetree.Pctf_constraint (_, _) -> loc.Location.loc_start.Lexing.pos_cnum
+ | Parsetree.Pctf_constraint (_, _)
+ | Parsetree.Pctf_attribute _ -> loc.Location.loc_start.Lexing.pos_cnum
| Parsetree.Pctf_inherit class_type ->
class_type.Parsetree.pcty_loc.Location.loc_start.Lexing.pos_cnum
| Parsetree.Pctf_extension _ -> assert false
@@ -456,6 +514,11 @@ module Analyser =
in
let (inher_l, eles) = f (pos_end + maybe_more) q in
(inh :: inher_l , eles_comments @ eles)
+ | Parsetree.Pctf_attribute _ ->
+ let (comment_opt, eles_comments) = get_comments_in_class last_pos loc.Location.loc_start.Lexing.pos_cnum in
+ let (inher_l, eles) = f loc.Location.loc_end.Lexing.pos_cnum q in
+ (inher_l, eles_comments @ eles)
+
| Parsetree.Pctf_extension _ -> assert false
in
f last_pos class_type_field_list
@@ -550,10 +613,86 @@ module Analyser =
let new_env = Odoc_env.add_value env v.val_name in
(maybe_more, new_env, [ Element_value v ])
- | Parsetree.Psig_exception exception_decl ->
- let name = exception_decl.Parsetree.pcd_name in
- let types_excep_decl =
- try Signature_search.search_exception table name.txt
+ | Parsetree.Psig_typext tyext ->
+ let new_env, types_ext_list, last_ext =
+ List.fold_left
+ (fun (env_acc, exts_acc, _) -> fun {Parsetree.pext_name = { txt = name }} ->
+ let complete_name = Name.concat current_module_name name in
+ let env_acc = Odoc_env.add_extension env_acc complete_name in
+ let types_ext =
+ try Signature_search.search_extension table name
+ with Not_found ->
+ raise (Failure (Odoc_messages.extension_not_found current_module_name name))
+ in
+ env_acc, ((name, types_ext) :: exts_acc), Some types_ext
+ )
+ (env, [], None)
+ tyext.Parsetree.ptyext_constructors
+ in
+ let ty_path, ty_params, priv =
+ match last_ext with
+ None -> assert false
+ | Some ext -> ext.ext_type_path, ext.ext_type_params, ext.ext_private
+ in
+ let new_te =
+ {
+ te_info = comment_opt;
+ te_type_name =
+ Odoc_env.full_type_name new_env (Name.from_path ty_path);
+ te_type_parameters =
+ List.map (Odoc_env.subst_type new_env) ty_params;
+ te_private = priv;
+ te_constructors = [];
+ te_loc = { loc_impl = None ; loc_inter = Some sig_item_loc} ;
+ te_code =
+ (
+ if !Odoc_global.keep_code then
+ Some (get_string_of_file pos_start_ele pos_end_ele)
+ else
+ None
+ ) ;
+ }
+ in
+ let rec analyse_extension_constructors maybe_more exts_acc types_ext_list =
+ match types_ext_list with
+ [] -> (maybe_more, List.rev exts_acc)
+ | (name, types_ext) :: q ->
+ let ext_loc_end = types_ext.Types.ext_loc.Location.loc_end.Lexing.pos_cnum in
+ let new_x =
+ {
+ xt_name = Name.concat current_module_name name ;
+ xt_args = List.map (Odoc_env.subst_type new_env) types_ext.ext_args ;
+ xt_ret = may_map (Odoc_env.subst_type new_env) types_ext.ext_ret_type ;
+ xt_type_extension = new_te;
+ xt_alias = None ;
+ xt_loc = { loc_impl = None ; loc_inter = Some types_ext.Types.ext_loc} ;
+ xt_text = None;
+ }
+ in
+ let pos_limit2 =
+ match q with
+ [] -> pos_limit
+ | (_, next) :: _ -> next.Types.ext_loc.Location.loc_start.Lexing.pos_cnum
+ in
+ let s = get_string_of_file ext_loc_end pos_limit2 in
+ let (maybe_more, comment_opt) = My_ir.just_after_special !file_name s in
+ new_x.xt_text <- comment_opt;
+ analyse_extension_constructors maybe_more (new_x :: exts_acc) q
+ in
+ let (maybe_more, exts) = analyse_extension_constructors 0 [] types_ext_list in
+ new_te.te_constructors <- exts;
+ let (maybe_more2, info_after_opt) =
+ My_ir.just_after_special
+ !file_name
+ (get_string_of_file (pos_end_ele + maybe_more) pos_limit)
+ in
+ new_te.te_info <- merge_infos new_te.te_info info_after_opt ;
+ (maybe_more + maybe_more2, new_env, [ Element_type_extension new_te ])
+
+ | Parsetree.Psig_exception ext ->
+ let name = ext.Parsetree.pext_name in
+ let types_ext =
+ try Signature_search.search_extension table name.txt
with Not_found ->
raise (Failure (Odoc_messages.exception_not_found current_module_name name.txt))
in
@@ -561,7 +700,8 @@ module Analyser =
{
ex_name = Name.concat current_module_name name.txt ;
ex_info = comment_opt ;
- ex_args = List.map (Odoc_env.subst_type env) types_excep_decl.exn_args ;
+ ex_args = List.map (Odoc_env.subst_type env) types_ext.ext_args ;
+ ex_ret = may_map (Odoc_env.subst_type env) types_ext.ext_ret_type ;
ex_alias = None ;
ex_loc = { loc_impl = None ; loc_inter = Some sig_item_loc } ;
ex_code =
@@ -579,7 +719,7 @@ module Analyser =
(get_string_of_file pos_end_ele pos_limit)
in
e.ex_info <- merge_infos e.ex_info info_after_opt ;
- let new_env = Odoc_env.add_exception env e.ex_name in
+ let new_env = Odoc_env.add_extension env e.ex_name in
(maybe_more, new_env, [ Element_exception e ])
| Parsetree.Psig_type name_type_decl_list ->
@@ -613,10 +753,10 @@ module Analyser =
| td :: _ -> td.Parsetree.ptype_loc.Location.loc_start.Lexing.pos_cnum
in
let (maybe_more, name_comment_list) =
- name_comment_from_type_kind
+ name_comment_from_type_decl
type_decl.Parsetree.ptype_loc.Location.loc_end.Lexing.pos_cnum
pos_limit2
- type_decl.Parsetree.ptype_kind
+ type_decl
in
print_DEBUG ("Type "^name.txt^" : "^(match assoc_com with None -> "sans commentaire" | Some c -> Odoc_misc.string_of_info c));
let f_DEBUG (name, c_opt) = print_DEBUG ("constructor/field "^name^": "^(match c_opt with None -> "sans commentaire" | Some c -> Odoc_misc.string_of_info c)) in
@@ -645,9 +785,11 @@ module Analyser =
ty_kind = type_kind;
ty_private = sig_type_decl.Types.type_private;
ty_manifest =
- (match sig_type_decl.Types.type_manifest with
- None -> None
- | Some t -> Some (Odoc_env.subst_type new_env t));
+ 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 =
(
diff --git a/ocamldoc/odoc_sig.mli b/ocamldoc/odoc_sig.mli
index f0c3c4a132..5dc4b4c8c0 100644
--- a/ocamldoc/odoc_sig.mli
+++ b/ocamldoc/odoc_sig.mli
@@ -27,10 +27,10 @@ module Signature_search :
@raise Not_found if error.*)
val search_value : tab -> string -> Types.type_expr
- (** This function returns the type expression list for the exception whose name is given,
+ (** This function returns the Types.extension_constructor for the extension whose name is given,
in the given table.
@raise Not_found if error.*)
- val search_exception : tab -> string -> Types.exception_declaration
+ val search_extension : tab -> string -> Types.extension_constructor
(** This function returns the Types.type_declaration for the type whose name is given,
in the given table.
@@ -42,7 +42,7 @@ module Signature_search :
@raise Not_found if error.*)
val search_class : tab -> string -> Types.class_declaration
- (** This function returns the Types.cltype_declaration for the class type whose name is given,
+ (** This function returns the Types.class_type_declaration for the class type whose name is given,
in the given table.
@raise Not_found if error.*)
val search_class_type : tab -> string -> Types.class_type_declaration
@@ -139,8 +139,14 @@ module Analyser :
[pos_end] is last char of the complete type definition.
[pos_limit] is the position of the last char we could use to look for a comment,
i.e. usually the beginning on the next element.*)
- val name_comment_from_type_kind :
- int -> int -> Parsetree.type_kind -> int * (string * Odoc_types.info option) list
+ val name_comment_from_type_decl :
+ int -> int -> Parsetree.type_declaration -> int * (string * Odoc_types.info option) list
+
+ (** This function converts a [Types.type_expr] into a [Odoc_type.type_kind],
+ by associating the comment found in the parstree of each object field, if any. *)
+ val manifest_structure :
+ Odoc_env.env -> (string * Odoc_types.info option) list ->
+ Types.type_expr -> Odoc_type.type_manifest
(** This function converts a [Types.type_kind] into a [Odoc_type.type_kind],
by associating the comment found in the parsetree of each constructor/field, if any.*)
diff --git a/ocamldoc/odoc_str.ml b/ocamldoc/odoc_str.ml
index 3c45c50705..7d99ff1079 100644
--- a/ocamldoc/odoc_str.ml
+++ b/ocamldoc/odoc_str.ml
@@ -15,7 +15,8 @@
module Name = Odoc_name
let string_of_variance t (co,cn) =
- if t.Odoc_type.ty_kind = Odoc_type.Type_abstract &&
+ if ( t.Odoc_type.ty_kind = Odoc_type.Type_abstract ||
+ t.Odoc_type.ty_kind = Odoc_type.Type_open ) &&
t.Odoc_type.ty_manifest = None
then
match (co, cn) with
@@ -106,6 +107,23 @@ let string_of_type_param_list t =
)
(if par then ")" else "")
+let string_of_type_extension_param_list te =
+ let par =
+ match te.Odoc_extension.te_type_parameters with
+ [] | [_] -> false
+ | _ -> true
+ in
+ Printf.sprintf "%s%s%s"
+ (if par then "(" else "")
+ (raw_string_of_type_list ", "
+ (List.map
+ (fun typ -> ("", typ))
+ te.Odoc_extension.te_type_parameters
+ )
+ )
+ (if par then ")" else "")
+
+
let string_of_class_type_param_list l =
let par =
match l with
@@ -155,91 +173,159 @@ let bool_of_private = function
let string_of_type t =
let module M = Odoc_type in
- "type "^
- (String.concat ""
- (List.map
- (fun (p, co, cn) ->
- (string_of_variance t (co, cn))^
- (Odoc_print.string_of_type_expr p)^" "
+ let module P = Printf in
+ let field_doc_str = function
+ | None -> ""
+ | Some t -> P.sprintf "(* %s *)" (Odoc_misc.string_of_info t)
+ in
+ let priv = bool_of_private t.M.ty_private in
+ let parameters_str =
+ String.concat " " (
+ List.map (fun (p, co, cn) ->
+ (string_of_variance t (co, cn)) ^ (Odoc_print.string_of_type_expr p)
+ ) t.M.ty_parameters
+ )
+ in
+ let manifest_str =
+ match t.M.ty_manifest with
+ | None -> ""
+ | Some (M.Object_type fields) ->
+ P.sprintf "= %s<\n%s\n>\n" (if priv then "private " else "") (
+ String.concat "\n" (
+ List.map (fun field ->
+ P.sprintf " %s : %s;%s" field.M.of_name
+ (Odoc_print.string_of_type_expr field.M.of_type)
+ (field_doc_str field.M.of_text)
+ ) fields
)
- t.M.ty_parameters
)
- )^
- let priv = bool_of_private (t.M.ty_private) in
- (Name.simple t.M.ty_name)^" "^
- (match t.M.ty_manifest with
- None -> ""
- | Some typ ->
+ | Some (M.Other typ) ->
"= " ^ (if priv then "private " else "" ) ^
- (Odoc_print.string_of_type_expr typ)^" "
- )^
- (match t.M.ty_kind with
- M.Type_abstract ->
- ""
- | M.Type_variant l ->
- "="^(if priv then " private" else "")^"\n"^
- (String.concat ""
- (List.map
- (fun cons ->
- " | "^cons.M.vc_name^
- (match cons.M.vc_args,cons.M.vc_ret with
+ (Odoc_print.string_of_type_expr typ) ^ " "
+ in
+ let type_kind_str =
+ match t.M.ty_kind with
+ | M.Type_abstract -> ""
+ | M.Type_variant l ->
+ P.sprintf "=%s\n%s\n" (if priv then " private" else "") (
+ String.concat "\n" (
+ List.map (fun cons ->
+ let comment =
+ match cons.M.vc_text with
+ | None -> ""
+ | Some t -> P.sprintf "(* %s *)" (Odoc_misc.string_of_info t)
+ in
+ let string_of_parameters lst =
+ String.concat " * " (
+ List.map (fun t -> "("^Odoc_print.string_of_type_expr t^")") lst
+ )
+ in
+ P.sprintf " | %s%s%s" cons.M.vc_name (
+ match cons.M.vc_args, cons.M.vc_ret with
| [], None -> ""
- | l, None ->
- " of " ^
- (String.concat " * "
- (List.map
- (fun t -> "("^Odoc_print.string_of_type_expr t^")") l))
+ | li, None -> " of " ^ (string_of_parameters li)
| [], Some r -> " : " ^ Odoc_print.string_of_type_expr r
- | l, Some r ->
- " : " ^
- (String.concat " * "
- (List.map
- (fun t -> "("^Odoc_print.string_of_type_expr t^")") l))
- ^ " -> " ^ Odoc_print.string_of_type_expr r
- )^
- (match cons.M.vc_text with
- None ->
- ""
- | Some t ->
- "(* "^(Odoc_misc.string_of_info t)^" *)"
- )^"\n"
- )
- l
- )
+ | li, Some r ->
+ P.sprintf " : %s -> %s" (string_of_parameters li)
+ (Odoc_print.string_of_type_expr r)
+ ) comment
+ ) l
+ )
)
+
+ | M.Type_open ->
+ "= .." (* FIXME MG: when introducing new constuctors next time,
+ thanks to setup a minimal correct output *)
| M.Type_record l ->
- "= "^(if priv then "private " else "")^"{\n"^
- (String.concat ""
- (List.map
- (fun record ->
- " "^(if record.M.rf_mutable then "mutable " else "")^
- record.M.rf_name^" : "^
- (Odoc_print.string_of_type_expr record.M.rf_type)^";"^
- (match record.M.rf_text with
- None ->
- ""
- | Some t ->
- "(* "^(Odoc_misc.string_of_info t)^" *)"
- )^"\n"
- )
- l
- )
- )^
- "}\n"
- )^
- (match t.M.ty_info with
- None -> ""
- | Some info -> Odoc_misc.string_of_info info)
+ P.sprintf "= %s{\n%s\n}\n" (if priv then "private " else "") (
+ String.concat "\n" (
+ List.map (fun field ->
+ P.sprintf " %s%s : %s;%s"
+ (if field.M.rf_mutable then "mutable " else "") field.M.rf_name
+ (Odoc_print.string_of_type_expr field.M.rf_type)
+ (field_doc_str field.M.rf_text)
+ ) l
+ )
+ )
+ in
+ P.sprintf "type %s %s %s%s%s" parameters_str (Name.simple t.M.ty_name)
+ manifest_str type_kind_str
+ (match t.M.ty_info with
+ | None -> ""
+ | Some info -> Odoc_misc.string_of_info info)
+
+let string_of_type_extension te =
+ let module M = Odoc_extension in
+ "type "
+ ^(String.concat ""
+ (List.map
+ (fun p -> (Odoc_print.string_of_type_expr p)^" ")
+ te.M.te_type_parameters
+ ))
+ ^te.M.te_type_name
+ ^" += "
+ ^(if (bool_of_private te.M.te_private) then "private " else "")
+ ^"\n"
+ ^(String.concat ""
+ (List.map
+ (fun x ->
+ " | "
+ ^(Name.simple x.M.xt_name)
+ ^(match x.M.xt_args, x.M.xt_ret with
+ | [], None -> ""
+ | l, None ->
+ " of " ^
+ (String.concat " * "
+ (List.map
+ (fun t -> "("^Odoc_print.string_of_type_expr t^")") l))
+ | [], Some r -> " : " ^ Odoc_print.string_of_type_expr r
+ | l, Some r ->
+ " : " ^
+ (String.concat " * "
+ (List.map
+ (fun t -> "("^Odoc_print.string_of_type_expr t^")") l))
+ ^ " -> " ^ Odoc_print.string_of_type_expr r
+ )
+ ^(match x.M.xt_alias with
+ None -> ""
+ | Some xa ->
+ " = "^
+ (match xa.M.xa_xt with
+ None -> xa.M.xa_name
+ | Some x2 -> x2.M.xt_name
+ )
+ )
+ ^(match x.M.xt_text with
+ None ->
+ ""
+ | Some t ->
+ "(* "^(Odoc_misc.string_of_info t)^" *)"
+ )^"\n"
+ )
+ te.M.te_constructors))
+ ^(match te.M.te_info with
+ None -> ""
+ | Some i -> Odoc_misc.string_of_info i
+ )
let string_of_exception e =
let module M = Odoc_exception in
"exception "^(Name.simple e.M.ex_name)^
- (match e.M.ex_args with
- [] -> ""
- | _ ->" : "^
- (String.concat " -> "
- (List.map (fun t -> "("^(Odoc_print.string_of_type_expr t)^")") e.M.ex_args)
- )
+ (match e.M.ex_args, e.M.ex_ret with
+ [], None -> ""
+ | l,None ->
+ " of "^
+ (String.concat " * "
+ (List.map (fun t -> "("^(Odoc_print.string_of_type_expr t)^")") l))
+ | [],Some r ->
+ " : "^
+ (Odoc_print.string_of_type_expr r)
+ | l,Some r ->
+ " : "^
+ (String.concat " * "
+ (List.map (fun t -> "("^(Odoc_print.string_of_type_expr t)^")") l))^
+ " -> "^
+ (Odoc_print.string_of_type_expr r)
)^
(match e.M.ex_alias with
None -> ""
diff --git a/ocamldoc/odoc_str.mli b/ocamldoc/odoc_str.mli
index 44278bb0fe..402a82d567 100644
--- a/ocamldoc/odoc_str.mli
+++ b/ocamldoc/odoc_str.mli
@@ -25,6 +25,10 @@ val string_of_type_list : ?par: bool -> string -> Types.type_expr list -> string
for the given type. *)
val string_of_type_param_list : Odoc_type.t_type -> string
+(** This function returns a string to represent the list of type parameters
+ for the given type extension. *)
+val string_of_type_extension_param_list : Odoc_extension.t_type_extension -> string
+
(** This function returns a string to represent the given list of
type parameters of a class or class type,
with a given separator. *)
@@ -37,6 +41,9 @@ val string_of_type : Odoc_type.t_type -> string
in the same form as the compiler. *)
val string_of_class_params : Odoc_class.t_class -> string
+(** @return a string to describe the given type extension. *)
+val string_of_type_extension : Odoc_extension.t_type_extension -> string
+
(** @return a string to describe the given exception. *)
val string_of_exception : Odoc_exception.t_exception -> string
diff --git a/ocamldoc/odoc_test.ml b/ocamldoc/odoc_test.ml
index cd7b5fa044..c68e853267 100644
--- a/ocamldoc/odoc_test.ml
+++ b/ocamldoc/odoc_test.ml
@@ -53,10 +53,11 @@ struct
p fmt "# type %s:\n" t.ty_name;
if self#must_display_types then
(
- p fmt "# manifest (Odoc_info.string_of_type_expr):\n<[%s]>\n"
+ p fmt "# manifest :\n<[%s]>\n"
(match t.ty_manifest with
None -> "None"
- | Some e -> Odoc_info.string_of_type_expr e
+ | Some (Object_type _fields) -> "< object type >" (* TODO *)
+ | Some (Other e) -> Odoc_info.string_of_type_expr e
);
);
diff --git a/ocamldoc/odoc_texi.ml b/ocamldoc/odoc_texi.ml
index 95354caac8..10d45c1c80 100644
--- a/ocamldoc/odoc_texi.ml
+++ b/ocamldoc/odoc_texi.ml
@@ -16,6 +16,7 @@ open Odoc_info
open Parameter
open Value
open Type
+open Extension
open Exception
open Class
open Module
@@ -42,24 +43,20 @@ let is = function
let pad_to n s =
let len = String.length s in
- if len < n
- then
- let s' = String.make n ' ' in
- String.blit s 0 s' 0 len ; s'
- else s
+ if len < n then s ^ String.make (n - len) ' ' else s
let indent nb_sp s =
let c = ref 0 in
let len = pred (String.length s) in
for i = 0 to len do if s.[i] = '\n' then incr c done ;
- let s' = String.make (succ len + (succ !c) * nb_sp ) ' ' in
+ let s' = Bytes.make (succ len + (succ !c) * nb_sp ) ' ' in
c := nb_sp ;
for i = 0 to len do
- s'.[!c] <- s.[i] ;
+ Bytes.set s' !c s.[i] ;
if s.[i] = '\n' then c := !c + nb_sp ;
incr c
done ;
- s'
+ Bytes.to_string s'
type subparts = [
| `Module of Odoc_info.Module.t_module
@@ -102,6 +99,7 @@ let module_subparts =
type indices = [
| `Type
+ | `Extension
| `Exception
| `Value
| `Class_att
@@ -114,6 +112,7 @@ type indices = [
let indices = function
| `Type -> "ty"
+ | `Extension -> "xt"
| `Exception -> "ex"
| `Value -> "va"
| `Class_att -> "ca"
@@ -125,6 +124,7 @@ let indices = function
let indices_names = [
"Types" , "ty" ;
+ "Extensions" , "xt" ;
"Exceptions" , "ex" ;
"Values" , "va" ;
"Class attributes", "ca" ;
@@ -440,17 +440,16 @@ class texi =
| Raw s -> Raw (Str.global_replace re "\n" s)
| List tel -> List (List.map self#fix_linebreaks tel)
| Enum tel -> Enum (List.map self#fix_linebreaks tel)
- | te -> te) t
+ | txt -> txt) t
method private soft_fix_linebreaks =
let re = Str.regexp "\n[ \t]*" in
fun ind t ->
- let rep = String.make (succ ind) ' ' in
- rep.[0] <- '\n' ;
+ let rep = "\n" ^ String.make ind ' ' in
List.map
(function
| Raw s -> Raw (Str.global_replace re rep s)
- | te -> te) t
+ | txt -> txt) t
(** {3 [text] values generation}
Generates [text] values out of description parts.
@@ -650,6 +649,12 @@ class texi =
(** Return Texinfo code for a type. *)
method texi_of_type ty =
Odoc_info.reset_type_names () ;
+ let entry_doc = function
+ | None -> [ Newline ]
+ | Some t ->
+ (Raw (indent 5 "\n(*\n") :: (self#soft_fix_linebreaks 8 (self#text_of_info (Some t))))
+ @ [ Raw " *)" ; Newline ]
+ in
let t =
[ self#fixedblock (
[ Newline ; minus ; Raw "type " ;
@@ -658,10 +663,24 @@ class texi =
let priv = ty.ty_private = Asttypes.Private in
( match ty.ty_manifest with
| None -> []
- | Some typ ->
+ | Some (Other typ) ->
(Raw " = ") ::
(Raw (if priv then "private " else "")) ::
- (self#text_of_short_type_expr (Name.father ty.ty_name) typ) ) @
+ (self#text_of_short_type_expr (Name.father ty.ty_name) typ)
+ | Some (Object_type l) ->
+ (Raw (" = "^(if priv then "private " else "")^"{\n")) ::
+ (List.flatten
+ (List.map
+ (fun r ->
+ [ Raw (" " ^ r.of_name ^ " : ") ] @
+ (self#text_of_short_type_expr
+ (Name.father r.of_name)
+ r.of_type) @
+ [ Raw " ;" ] @
+ (entry_doc r.of_text))
+ l ) )
+ @ [ Raw " }" ]
+ ) @
(
match ty.ty_kind with
| Type_abstract -> [ Newline ]
@@ -673,13 +692,8 @@ class texi =
(Raw (" | " ^ constr.vc_name)) ::
(Raw (self#string_of_type_args
constr.vc_args constr.vc_ret)) ::
- (match constr.vc_text with
- | None -> [ Newline ]
- | Some t ->
- (Raw (indent 5 "\n(*\n ") ::
- self#soft_fix_linebreaks 8 (self#text_of_info (Some t))) @
- [ Raw " *)" ; Newline ]
- ) ) l ) )
+ (entry_doc constr.vc_text)
+ ) l ) )
| Type_record l ->
(Raw (" = "^(if priv then "private " else "")^"{\n")) ::
(List.flatten
@@ -690,19 +704,61 @@ class texi =
(Name.father r.rf_name)
r.rf_type) @
[ Raw " ;" ] @
- (match r.rf_text with
- | None -> [ Newline ]
- | Some t ->
- ((Raw (indent 5 "\n(*\n ")) ::
- (self#soft_fix_linebreaks 8 (self#text_of_info (Some t)))) @
- [ Raw " *)" ; Newline ] ) )
+ (entry_doc r.rf_text)
+ )
l ) )
@ [ Raw " }" ]
+ | Type_open -> [ Raw " = .." ; Newline ]
) ) ;
self#index `Type ty.ty_name ; Newline ] @
(self#text_of_info ty.ty_info) in
self#texi_of_text t
+ (** Return Texinfo code for a type extension. *)
+ method texi_of_type_extension m_name te =
+ Odoc_info.reset_type_names () ;
+ let t =
+ ( self#fixedblock (
+ [ Newline ; minus ;
+ Raw "type " ;
+ Raw (match te.te_type_parameters with
+ | [] -> ""
+ | [ tp ] ->
+ Printf.sprintf "%s "
+ (Odoc_info.string_of_type_expr tp)
+ | l ->
+ Printf.sprintf "(%s) "
+ (String.concat ", "
+ (List.map Odoc_info.string_of_type_expr l))) ;
+ Raw (self#relative_idents m_name te.te_type_name) ;
+ Raw (" +=" ^
+ (if te.te_private = Asttypes.Private
+ then " private" else "")^"\n") ] @
+ (List.flatten
+ (List.map
+ (fun x ->
+ (Raw (" | " ^ (Name.simple x.xt_name))) ::
+ (Raw (self#string_of_type_args
+ x.xt_args x.xt_ret)) ::
+ (match x.xt_alias with
+ | None -> []
+ | Some xa ->
+ [ Raw " = " ;
+ Raw ( match xa.xa_xt with
+ | None -> xa.xa_name
+ | Some x -> x.xt_name ) ]) @
+ (match x.xt_text with
+ | None -> [ Newline ]
+ | Some t ->
+ (Raw (indent 5 "\n(* ") ::
+ self#soft_fix_linebreaks 8
+ (self#text_of_info (Some t))) @
+ [ Raw " *)" ; Newline ] ) @
+ [self#index `Extension x.xt_name ] )
+ te.te_constructors ) ) ) ) ::
+ (self#text_of_info te.te_info) in
+ self#texi_of_text t
+
(** Return Texinfo code for an exception. *)
method texi_of_exception e =
Odoc_info.reset_type_names () ;
@@ -710,7 +766,7 @@ class texi =
[ self#fixedblock
( [ Newline ; minus ; Raw "exception " ;
Raw (Name.simple e.ex_name) ;
- Raw (self#string_of_type_args e.ex_args None) ] @
+ Raw (self#string_of_type_args e.ex_args e.ex_ret) ] @
(match e.ex_alias with
| None -> []
| Some ea -> [ Raw " = " ; Raw
@@ -838,6 +894,7 @@ class texi =
| Element_class c -> self#texi_of_class c
| Element_class_type ct -> self#texi_of_class_type ct
| Element_value v -> self#texi_of_value v
+ | Element_type_extension te -> self#texi_of_type_extension module_name te
| Element_exception e -> self#texi_of_exception e
| Element_type t -> self#texi_of_type t
| Element_module_comment t ->
@@ -1198,6 +1255,7 @@ class texi =
method scan_for_index_in_mod = function
(* no recursion *)
| Element_value _ -> self#do_index `Value
+ | Element_type_extension _ -> self#do_index `Extension
| Element_exception _ -> self#do_index `Exception
| Element_type _ -> self#do_index `Type
| Element_included_module _
diff --git a/ocamldoc/odoc_text.ml b/ocamldoc/odoc_text.ml
index 4fd30e0ee9..eb3c562691 100644
--- a/ocamldoc/odoc_text.ml
+++ b/ocamldoc/odoc_text.ml
@@ -128,6 +128,7 @@ module Texter =
| RK_class_type -> "classtype"
| RK_value -> "val"
| RK_type -> "type"
+ | RK_extension -> "extension"
| RK_exception -> "exception"
| RK_attribute -> "attribute"
| RK_method -> "method"
diff --git a/ocamldoc/odoc_text_lexer.mll b/ocamldoc/odoc_text_lexer.mll
index aaaff10578..c8dda36aa9 100644
--- a/ocamldoc/odoc_text_lexer.mll
+++ b/ocamldoc/odoc_text_lexer.mll
@@ -151,6 +151,7 @@ let end_verb = blank_nl"v}"
let begin_ele_ref = "{!"blank_nl | "{!"
let begin_val_ref = "{!val:"blank_nl | "{!val:"
let begin_typ_ref = "{!type:"blank_nl | "{!type:"
+let begin_ext_ref = "{!extension:"blank_nl | "{!extension:"
let begin_exc_ref = "{!exception:"blank_nl | "{!exception:"
let begin_mod_ref = "{!module:"blank_nl | "{!module:"
let begin_modt_ref = "{!modtype:"blank_nl | "{!modtype:"
@@ -529,6 +530,23 @@ rule main = parse
)
}
+| begin_ext_ref
+ {
+ incr_cpts lexbuf ;
+ if !verb_mode || !target_mode || !code_pre_mode || !open_brackets >= 1 then
+ Char (Lexing.lexeme lexbuf)
+ else
+ if not !ele_ref_mode then
+ (
+ ele_ref_mode := true;
+ EXT_REF
+ )
+ else
+ (
+ Char (Lexing.lexeme lexbuf)
+ )
+ }
+
| begin_exc_ref
{
incr_cpts lexbuf ;
diff --git a/ocamldoc/odoc_text_parser.mly b/ocamldoc/odoc_text_parser.mly
index c10425ccb4..b4118c4f21 100644
--- a/ocamldoc/odoc_text_parser.mly
+++ b/ocamldoc/odoc_text_parser.mly
@@ -52,6 +52,7 @@ let print_DEBUG s = print_string s; print_newline ()
%token ELE_REF
%token VAL_REF
%token TYP_REF
+%token EXT_REF
%token EXC_REF
%token MOD_REF
%token MODT_REF
@@ -113,6 +114,7 @@ ele_ref_kind:
ELE_REF { None }
| VAL_REF { Some RK_value }
| TYP_REF { Some RK_type }
+| EXT_REF { Some RK_extension }
| EXC_REF { Some RK_exception }
| MOD_REF { Some RK_module }
| MODT_REF { Some RK_module_type }
diff --git a/ocamldoc/odoc_to_text.ml b/ocamldoc/odoc_to_text.ml
index c913875704..1c7f6ba7fb 100644
--- a/ocamldoc/odoc_to_text.ml
+++ b/ocamldoc/odoc_to_text.ml
@@ -336,29 +336,36 @@ class virtual to_text =
(** @return [text] value for an exception. *)
method text_of_exception e =
let s_name = Name.simple e.ex_name in
+ let father = Name.father e.ex_name in
Format.fprintf Format.str_formatter "@[<hov 2>exception %s" s_name ;
- (match e.ex_args with
- [] -> ()
- | _ ->
- Format.fprintf Format.str_formatter "@ of "
- );
- let s = self#normal_type_list
- ~par: false (Name.father e.ex_name) " * " e.ex_args
- in
- let s2 =
- Format.fprintf Format.str_formatter "%s" s ;
- (match e.ex_alias with
- None -> ()
- | Some ea ->
- Format.fprintf Format.str_formatter " = %s"
- (
- match ea.ea_ex with
- None -> ea.ea_name
- | Some e -> e.ex_name
- )
- );
- Format.flush_str_formatter ()
- in
+ (match e.ex_args, e.ex_ret with
+ [], None -> ()
+ | l, None ->
+ Format.fprintf Format.str_formatter " %s@ %s"
+ "of"
+ (self#normal_type_list ~par: false father " * " l)
+ | [], Some r ->
+ Format.fprintf Format.str_formatter " %s@ %s"
+ ":"
+ (self#normal_type father r)
+ | l, Some r ->
+ Format.fprintf Format.str_formatter " %s@ %s@ %s@ %s"
+ ":"
+ (self#normal_type_list ~par: false father " * " l)
+ "->"
+ (self#normal_type father r)
+ );
+ (match e.ex_alias with
+ None -> ()
+ | Some ea ->
+ Format.fprintf Format.str_formatter " = %s"
+ (
+ match ea.ea_ex with
+ None -> ea.ea_name
+ | Some e -> e.ex_name
+ )
+ );
+ let s2 = Format.flush_str_formatter () in
[ CodePre s2 ] @
[Latex ("\\index{"^(self#label s_name)^"@\\verb`"^(self#label ~no_:false s_name)^"`}\n")] @
(self#text_of_info e.ex_info)
diff --git a/ocamldoc/odoc_type.ml b/ocamldoc/odoc_type.ml
index ef9699e607..dadc6b1bad 100644
--- a/ocamldoc/odoc_type.ml
+++ b/ocamldoc/odoc_type.ml
@@ -40,6 +40,17 @@ type type_kind =
(** constructors *)
| Type_record of record_field list
(** fields *)
+ | Type_open
+
+type object_field = {
+ of_name : string ;
+ of_type : Types.type_expr ;
+ mutable of_text : Odoc_types.info option ; (** optional user description *)
+}
+
+type type_manifest =
+ | Other of Types.type_expr (** Type manifest directly taken from Typedtre. *)
+ | Object_type of object_field list
(** Representation of a type. *)
type t_type = {
@@ -49,7 +60,7 @@ type t_type = {
(** type parameters: (type, covariant, contravariant) *)
ty_kind : type_kind ;
ty_private : private_flag;
- ty_manifest : Types.type_expr option; (** type manifest *)
+ ty_manifest : type_manifest option;
mutable ty_loc : Odoc_types.location ;
mutable ty_code : string option;
}
diff --git a/ocamldoc/odoc_types.ml b/ocamldoc/odoc_types.ml
index eccc852d67..9d7824aae1 100644
--- a/ocamldoc/odoc_types.ml
+++ b/ocamldoc/odoc_types.ml
@@ -17,6 +17,7 @@ type ref_kind =
| RK_class_type
| RK_value
| RK_type
+ | RK_extension
| RK_exception
| RK_attribute
| RK_method
diff --git a/ocamldoc/odoc_types.mli b/ocamldoc/odoc_types.mli
index 7819a2346b..f9456ccd85 100644
--- a/ocamldoc/odoc_types.mli
+++ b/ocamldoc/odoc_types.mli
@@ -20,6 +20,7 @@ type ref_kind =
| RK_class_type
| RK_value
| RK_type
+ | RK_extension
| RK_exception
| RK_attribute
| RK_method
diff --git a/otherlibs/Makefile.shared b/otherlibs/Makefile.shared
index 6c2fc5d67a..9bed5f7604 100644
--- a/otherlibs/Makefile.shared
+++ b/otherlibs/Makefile.shared
@@ -19,7 +19,7 @@ include $(ROOTDIR)/config/Makefile
# Compilation options
CC=$(BYTECC)
CAMLRUN=$(ROOTDIR)/boot/ocamlrun
-COMPFLAGS=-w +33..39 -warn-error A -bin-annot -g $(EXTRACAMLFLAGS)
+COMPFLAGS=-w +33..39 -warn-error A -bin-annot -g -safe-string $(EXTRACAMLFLAGS)
MKLIB=$(CAMLRUN) $(ROOTDIR)/tools/ocamlmklib
# Variables to be defined by individual libraries:
diff --git a/otherlibs/bigarray/.depend b/otherlibs/bigarray/.depend
index 4df63a3e32..d705f2022e 100644
--- a/otherlibs/bigarray/.depend
+++ b/otherlibs/bigarray/.depend
@@ -1,21 +1,21 @@
bigarray_stubs.o: bigarray_stubs.c ../../byterun/alloc.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h bigarray.h \
- ../../byterun/config.h ../../byterun/mlvalues.h ../../byterun/custom.h \
- ../../byterun/fail.h ../../byterun/intext.h ../../byterun/io.h \
- ../../byterun/hash.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/int64_native.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h bigarray.h \
+ ../../byterun/config.h ../../byterun/mlvalues.h ../../byterun/custom.h \
+ ../../byterun/fail.h ../../byterun/intext.h ../../byterun/io.h \
+ ../../byterun/hash.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/int64_native.h
mmap_unix.o: mmap_unix.c bigarray.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/mlvalues.h ../../byterun/config.h ../../byterun/misc.h \
- ../../byterun/custom.h ../../byterun/mlvalues.h ../../byterun/fail.h \
- ../../byterun/io.h ../../byterun/sys.h ../../byterun/signals.h
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/mlvalues.h ../../byterun/config.h ../../byterun/misc.h \
+ ../../byterun/custom.h ../../byterun/mlvalues.h ../../byterun/fail.h \
+ ../../byterun/io.h ../../byterun/sys.h ../../byterun/signals.h
mmap_win32.o: mmap_win32.c bigarray.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/mlvalues.h ../../byterun/config.h ../../byterun/misc.h \
- ../../byterun/alloc.h ../../byterun/mlvalues.h ../../byterun/custom.h \
- ../../byterun/fail.h ../../byterun/sys.h ../unix/unixsupport.h
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/mlvalues.h ../../byterun/config.h ../../byterun/misc.h \
+ ../../byterun/alloc.h ../../byterun/mlvalues.h ../../byterun/custom.h \
+ ../../byterun/fail.h ../../byterun/sys.h ../unix/unixsupport.h
bigarray.cmi :
bigarray.cmo : bigarray.cmi
bigarray.cmx : bigarray.cmi
diff --git a/otherlibs/bigarray/mmap_unix.c b/otherlibs/bigarray/mmap_unix.c
index 8a93a06b11..cdcfe3ce32 100644
--- a/otherlibs/bigarray/mmap_unix.c
+++ b/otherlibs/bigarray/mmap_unix.c
@@ -153,7 +153,7 @@ CAMLprim value caml_ba_map_file(value vfd, value vkind, value vlayout,
}
}
/* Determine offset so that the mapping starts at the given file pos */
- page = getpagesize();
+ page = sysconf(_SC_PAGESIZE);
delta = (uintnat) startpos % page;
/* Do the mmap */
shared = Bool_val(vshared) ? MAP_SHARED : MAP_PRIVATE;
@@ -189,7 +189,7 @@ CAMLprim value caml_ba_map_file_bytecode(value * argv, int argn)
void caml_ba_unmap_file(void * addr, uintnat len)
{
#if defined(HAS_MMAP)
- uintnat page = getpagesize();
+ uintnat page = sysconf(_SC_PAGESIZE);
uintnat delta = (uintnat) addr % page;
if (len == 0) return; /* PR#5463 */
addr = (void *)((uintnat)addr - delta);
diff --git a/otherlibs/dynlink/Makefile b/otherlibs/dynlink/Makefile
index 15b01921bb..6284a5283e 100644
--- a/otherlibs/dynlink/Makefile
+++ b/otherlibs/dynlink/Makefile
@@ -21,7 +21,8 @@ OCAMLC = $(OCAMLRUN) $(ROOTDIR)/ocamlc -nostdlib -I $(ROOTDIR)/stdlib
OCAMLOPT = $(OCAMLRUN) $(ROOTDIR)/ocamlopt -nostdlib -I $(ROOTDIR)/stdlib
INCLUDES=-I ../../utils -I ../../typing -I ../../bytecomp -I ../../asmcomp
-COMPFLAGS=-w +33..39 -warn-error A -bin-annot -I ../../stdlib $(INCLUDES)
+COMPFLAGS=-w +33..39 -warn-error A -bin-annot -safe-string \
+ -I ../../stdlib $(INCLUDES)
OBJS=dynlinkaux.cmo dynlink.cmo
diff --git a/otherlibs/dynlink/dynlink.ml b/otherlibs/dynlink/dynlink.ml
index fee98f1c1b..47409ad361 100644
--- a/otherlibs/dynlink/dynlink.ml
+++ b/otherlibs/dynlink/dynlink.ml
@@ -79,13 +79,16 @@ let allow_extension = ref true
let check_consistency file_name cu =
try
List.iter
- (fun (name, 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)
+ (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))
@@ -113,15 +116,21 @@ let prohibit names =
(* 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
+ 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();
- add_available_units !default_crcs;
+ 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 *)
@@ -152,7 +161,9 @@ let digest_interface unit loadpath =
raise (Error(File_not_found shortname)) in
let ic = open_in_bin filename in
try
- let buffer = Misc.input_bytes ic (String.length Config.cmi_magic_number) in
+ 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(Error(Corrupted_interface filename))
@@ -161,7 +172,7 @@ let digest_interface unit loadpath =
close_in ic;
let crc =
match cmi.Cmi_format.cmi_crcs with
- (_, crc) :: _ -> crc
+ (_, Some crc) :: _ -> crc
| _ -> raise(Error(Corrupted_interface filename))
in
crc
@@ -189,7 +200,7 @@ let check_unsafe_module cu =
(* Load in-core and execute a bytecode object file *)
-external register_code_fragment: string -> int -> string -> unit
+external register_code_fragment: bytes -> int -> string -> unit
= "caml_register_code_fragment"
let load_compunit ic file_name file_digest compunit =
@@ -199,14 +210,14 @@ let load_compunit ic file_name file_digest compunit =
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;
- String.unsafe_set code compunit.cu_codesize (Char.chr Opcodes.opRETURN);
- String.unsafe_set code (compunit.cu_codesize + 1) '\000';
- String.unsafe_set code (compunit.cu_codesize + 2) '\000';
- String.unsafe_set code (compunit.cu_codesize + 3) '\000';
- String.unsafe_set code (compunit.cu_codesize + 4) '\001';
- String.unsafe_set code (compunit.cu_codesize + 5) '\000';
- String.unsafe_set code (compunit.cu_codesize + 6) '\000';
- String.unsafe_set code (compunit.cu_codesize + 7) '\000';
+ 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;
@@ -242,7 +253,7 @@ let loadfile file_name =
seek_in ic 0;
try
let buffer =
- try Misc.input_bytes ic (String.length Config.cmo_magic_number)
+ 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
diff --git a/otherlibs/dynlink/natdynlink.ml b/otherlibs/dynlink/natdynlink.ml
index fd06d7c70c..597d60fb5f 100644
--- a/otherlibs/dynlink/natdynlink.ml
+++ b/otherlibs/dynlink/natdynlink.ml
@@ -15,9 +15,9 @@
type handle
-external ndl_open: string -> bool -> handle * string = "caml_natdynlink_open"
+external ndl_open: string -> bool -> handle * bytes = "caml_natdynlink_open"
external ndl_run: handle -> string -> unit = "caml_natdynlink_run"
-external ndl_getmap: unit -> string = "caml_natdynlink_getmap"
+external ndl_getmap: unit -> bytes = "caml_natdynlink_getmap"
external ndl_globals_inited: unit -> int = "caml_natdynlink_globals_inited"
type linking_error =
@@ -41,11 +41,7 @@ exception Error of error
open Cmx_format
(* Copied from config.ml to avoid dependencies *)
-let cmxs_magic_number = "Caml2007D001"
-
-(* Copied from compilenv.ml to avoid dependencies *)
-let cmx_not_found_crc =
- "\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000\000"
+let cmxs_magic_number = "Caml2007D002"
let dll_filename fname =
if Filename.is_implicit fname then Filename.concat (Sys.getcwd ()) fname
@@ -59,7 +55,7 @@ let read_file filename priv =
if Obj.tag (Obj.repr res) = Obj.string_tag
then raise (Error (Cannot_open_dll (Obj.magic res)));
- let header : dynheader = Marshal.from_string data 0 in
+ let header : dynheader = Marshal.from_bytes data 0 in
if header.dynu_magic <> cmxs_magic_number
then raise(Error(Not_a_bytecode_file dll));
(dll, handle, header.dynu_units)
@@ -92,7 +88,7 @@ let inited = ref false
let default_available_units () =
let map : (string*Digest.t*Digest.t*string list) list =
- Marshal.from_string (ndl_getmap ()) 0 in
+ Marshal.from_bytes (ndl_getmap ()) 0 in
let exe = Sys.executable_name in
let rank = ref 0 in
global_state :=
@@ -114,23 +110,26 @@ let init () =
let add_check_ifaces allow_ext filename ui ifaces =
List.fold_left
- (fun ifaces (name, 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))
+ (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 filename ui implems =
List.iter
- (fun (name, crc) ->
+ (fun (name, crco) ->
match name with
|"Out_of_memory"
|"Sys_error"
@@ -147,13 +146,15 @@ let check_implems filename ui implems =
| _ ->
try
let (old_crc,old_src,state) = StrMap.find name implems in
- if crc <> cmx_not_found_crc && old_crc <> crc
- then raise(Error(Inconsistent_implementation(name)))
- else match state with
- | Check_inited i ->
- if ndl_globals_inited() < i
- then raise(Error(Unavailable_unit name))
- | Loaded -> ()
+ 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
diff --git a/otherlibs/graph/.depend b/otherlibs/graph/.depend
index b4b531d43a..ab9faa619a 100644
--- a/otherlibs/graph/.depend
+++ b/otherlibs/graph/.depend
@@ -1,63 +1,103 @@
-color.o: color.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h
-draw.o: draw.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h
-dump_img.o: dump_img.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h image.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h
-events.o: events.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/signals.h
-fill.o: fill.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h
-image.o: image.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h image.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/custom.h
-make_img.o: make_img.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h image.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h
-open.o: open.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/callback.h ../../byterun/fail.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h
-point_col.o: point_col.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h
-sound.o: sound.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h
-subwindow.o: subwindow.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h
-text.o: text.c libgraph.h ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h
+color.o: color.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h \
+
+draw.o: draw.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h
+dump_img.o: dump_img.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h image.h \
+ ../../byterun/alloc.h ../../byterun/mlvalues.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h
+events.o: events.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/signals.h
+fill.o: fill.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h
+image.o: image.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h image.h \
+ ../../byterun/alloc.h ../../byterun/mlvalues.h ../../byterun/custom.h
+make_img.o: make_img.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h image.h \
+ ../../byterun/memory.h ../../byterun/gc.h ../../byterun/mlvalues.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h
+open.o: open.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/callback.h ../../byterun/fail.h \
+ ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h
+point_col.o: point_col.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h
+sound.o: sound.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h
+subwindow.o: subwindow.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h
+text.o: text.c libgraph.h \
+ \
+ \
+ \
+ ../../byterun/mlvalues.h ../../byterun/compatibility.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h
graphics.cmi :
graphicsX11.cmi :
graphics.cmo : graphics.cmi
diff --git a/otherlibs/graph/libgraph.h b/otherlibs/graph/libgraph.h
index e75ee801cc..71204e3133 100644
--- a/otherlibs/graph/libgraph.h
+++ b/otherlibs/graph/libgraph.h
@@ -15,6 +15,7 @@
#include <X11/Xlib.h>
#include <X11/Xutil.h>
#include <mlvalues.h>
+#include <misc.h>
struct canvas {
int w, h; /* Dimensions of the drawable */
@@ -73,7 +74,7 @@ extern int caml_gr_bits_per_pixel;
#endif
#endif
-extern void caml_gr_fail(char *fmt, char *arg);
+extern void caml_gr_fail(char *fmt, char *arg) Noreturn;
extern void caml_gr_check_open(void);
extern unsigned long caml_gr_pixel_rgb(int rgb);
extern int caml_gr_rgb_pixel(long unsigned int pixel);
diff --git a/otherlibs/num/.depend b/otherlibs/num/.depend
index 32d691cc80..51b180f5d8 100644
--- a/otherlibs/num/.depend
+++ b/otherlibs/num/.depend
@@ -1,6 +1,6 @@
bng.o: bng.c bng.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/compatibility.h bng_amd64.c \
- bng_digit.c
+ ../../byterun/../config/s.h ../../byterun/compatibility.h bng_amd64.c \
+ bng_digit.c
bng_amd64.o: bng_amd64.c
bng_arm64.o: bng_arm64.c
bng_digit.o: bng_digit.c
@@ -8,14 +8,14 @@ bng_ia32.o: bng_ia32.c
bng_ppc.o: bng_ppc.c
bng_sparc.o: bng_sparc.c
nat_stubs.o: nat_stubs.c ../../byterun/alloc.h \
- ../../byterun/compatibility.h ../../byterun/misc.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/config.h ../../byterun/custom.h ../../byterun/intext.h \
- ../../byterun/io.h ../../byterun/fail.h ../../byterun/hash.h \
- ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/mlvalues.h bng.h nat.h
+ ../../byterun/compatibility.h ../../byterun/misc.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/config.h ../../byterun/custom.h ../../byterun/intext.h \
+ ../../byterun/io.h ../../byterun/fail.h ../../byterun/hash.h \
+ ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/mlvalues.h bng.h nat.h
arith_flags.cmi :
arith_status.cmi :
big_int.cmi : nat.cmi
diff --git a/otherlibs/num/big_int.ml b/otherlibs/num/big_int.ml
index 939bbfb8ee..847d158324 100644
--- a/otherlibs/num/big_int.ml
+++ b/otherlibs/num/big_int.ml
@@ -625,15 +625,15 @@ let square_big_int bi =
else s <- the round number and the result_int is false *)
let round_futur_last_digit s off_set length =
let l = pred (length + off_set) in
- if Char.code(String.get s l) >= Char.code '5'
+ if Char.code(Bytes.get s l) >= Char.code '5'
then
let rec round_rec l =
if l < off_set then true else begin
- let current_char = String.get s l in
+ let current_char = Bytes.get s l in
if current_char = '9' then
- (String.set s l '0'; round_rec (pred l))
+ (Bytes.set s l '0'; round_rec (pred l))
else
- (String.set s l (Char.chr (succ (Char.code current_char)));
+ (Bytes.set s l (Char.chr (succ (Char.code current_char)));
false)
end
in round_rec (pred l)
@@ -652,17 +652,19 @@ let approx_big_int prec bi =
(big_int_of_string "963295986"))
(big_int_of_string "100000000")))) in
let s =
- string_of_big_int (div_big_int bi (power_int_positive_int 10 n)) in
+ Bytes.unsafe_of_string
+ (string_of_big_int (div_big_int bi (power_int_positive_int 10 n)))
+ in
let (sign, off, len) =
- if String.get s 0 = '-'
+ if Bytes.get s 0 = '-'
then ("-", 1, succ prec)
else ("", 0, prec) in
if (round_futur_last_digit s off (succ prec))
then (sign^"1."^(String.make prec '0')^"e"^
- (string_of_int (n + 1 - off + String.length s)))
- else (sign^(String.sub s off 1)^"."^
- (String.sub s (succ off) (pred prec))
- ^"e"^(string_of_int (n - succ off + String.length s)))
+ (string_of_int (n + 1 - off + Bytes.length s)))
+ else (sign^(Bytes.sub_string s off 1)^"."^
+ (Bytes.sub_string s (succ off) (pred prec))
+ ^"e"^(string_of_int (n - succ off + Bytes.length s)))
(* Logical operations *)
diff --git a/otherlibs/num/big_int.mli b/otherlibs/num/big_int.mli
index 276108f902..738730a79a 100644
--- a/otherlibs/num/big_int.mli
+++ b/otherlibs/num/big_int.mli
@@ -187,5 +187,5 @@ val nat_of_big_int : big_int -> nat
val big_int_of_nat : nat -> big_int
val base_power_big_int: int -> int -> big_int -> big_int
val sys_big_int_of_string: string -> int -> int -> big_int
-val round_futur_last_digit : string -> int -> int -> bool
+val round_futur_last_digit : bytes -> int -> int -> bool
val approx_big_int: int -> big_int -> string
diff --git a/otherlibs/num/nat.ml b/otherlibs/num/nat.ml
index 59f57ee7d8..90cb471c1b 100644
--- a/otherlibs/num/nat.ml
+++ b/otherlibs/num/nat.ml
@@ -282,18 +282,15 @@ let raw_string_of_digit nat off =
and s1 = string_of_int (nth_digit_nat a_1 0) in
let len = String.length s1 in
if leading_digits < 10 then begin
- let result = String.make (max_superscript_10_power_in_int+1) '0' in
- String.set result 0
- (Char.chr (48 + leading_digits));
- String.blit s1 0
- result (String.length result - len) len;
- result
+ let result = Bytes.make (max_superscript_10_power_in_int+1) '0' in
+ Bytes.set result 0 (Char.chr (48 + leading_digits));
+ String.blit s1 0 result (Bytes.length result - len) len;
+ Bytes.to_string result
end else begin
- let result = String.make (max_superscript_10_power_in_int+2) '0' in
+ let result = Bytes.make (max_superscript_10_power_in_int+2) '0' in
String.blit (string_of_int leading_digits) 0 result 0 2;
- String.blit s1 0
- result (String.length result - len) len;
- result
+ String.blit s1 0 result (Bytes.length result - len) len;
+ Bytes.to_string result
end
end
@@ -344,7 +341,7 @@ let int_to_string int s pos_ref base times =
let i = ref int
and j = ref times in
while ((!i != 0) || (!j != 0)) && (!pos_ref != -1) do
- String.set s !pos_ref (String.get digits (!i mod base));
+ Bytes.set s !pos_ref (String.get digits (!i mod base));
decr pos_ref;
decr j;
i := !i / base
@@ -466,7 +463,7 @@ let unadjusted_string_of_nat nat off len_nat =
if len > biggest_int / (succ pmax)
then failwith "number too long"
else let len_s = (succ pmax) * len in
- let s = String.make len_s '0'
+ let s = Bytes.make len_s '0'
and pos_ref = ref len_s in
len_copy := pred !len_copy;
blit_nat copy1 0 nat off len;
@@ -488,7 +485,7 @@ let unadjusted_string_of_nat nat off len_nat =
blit_nat copy1 0 copy2 0 !len_copy;
set_digit_nat copy1 !len_copy 0
done;
- s
+ Bytes.unsafe_to_string s
let string_of_nat nat =
let s = unadjusted_string_of_nat nat 0 (length_nat nat)
diff --git a/otherlibs/num/ratio.ml b/otherlibs/num/ratio.ml
index fe0170f299..5bb04b6474 100644
--- a/otherlibs/num/ratio.ml
+++ b/otherlibs/num/ratio.ml
@@ -438,7 +438,8 @@ let approx_ratio_fix n r =
r.denominator)) in
(* Round up and add 1 in front if needed *)
let s2 =
- if round_futur_last_digit s1 0 (String.length s1)
+ if round_futur_last_digit (Bytes.unsafe_of_string s1) 0
+ (String.length s1)
then "1" ^ s1
else s1 in
let l2 = String.length s2 - 1 in
@@ -447,18 +448,18 @@ let approx_ratio_fix n r =
if s2 without last digit is yy with <= n digits:
<sign> 0 . 0yy *)
if l2 > n then begin
- let s = String.make (l2 + 2) '0' in
- String.set s 0 (if sign_r = -1 then '-' else '+');
+ let s = Bytes.make (l2 + 2) '0' in
+ Bytes.set s 0 (if sign_r = -1 then '-' else '+');
String.blit s2 0 s 1 (l2 - n);
- String.set s (l2 - n + 1) '.';
+ Bytes.set s (l2 - n + 1) '.';
String.blit s2 (l2 - n) s (l2 - n + 2) n;
- s
+ Bytes.unsafe_to_string s
end else begin
- let s = String.make (n + 3) '0' in
- String.set s 0 (if sign_r = -1 then '-' else '+');
- String.set s 2 '.';
+ let s = Bytes.make (n + 3) '0' in
+ Bytes.set s 0 (if sign_r = -1 then '-' else '+');
+ Bytes.set s 2 '.';
String.blit s2 0 s (n + 3 - l2) l2;
- s
+ Bytes.unsafe_to_string s
end
end else begin
(* Dubious; what is this code supposed to do? *)
@@ -468,10 +469,10 @@ let approx_ratio_fix n r =
(base_power_big_int
10 (-n) r.denominator)) in
let len = succ (String.length s) in
- let s' = String.make len '0' in
- String.set s' 0 (if sign_r = -1 then '-' else '+');
+ let s' = Bytes.make len '0' in
+ Bytes.set s' 0 (if sign_r = -1 then '-' else '+');
String.blit s 0 s' 1 (pred len);
- s'
+ Bytes.unsafe_to_string s'
end
(* Number of digits of the decimal representation of an int *)
@@ -488,11 +489,8 @@ let approx_ratio_exp n r =
else
let sign_r = sign_ratio r
and i = ref (n + 3) in
- if sign_r = 0
- then
- let s = String.make (n + 5) '0' in
- (String.blit "+0." 0 s 0 3);
- (String.blit "e0" 0 s !i 2); s
+ if sign_r = 0 then
+ String.concat "" ["+0."; String.make n '0'; "e0"]
else
let msd = msd_ratio (abs_ratio r) in
let k = n - msd in
@@ -508,28 +506,29 @@ let approx_ratio_exp n r =
10 k (abs_big_int r.numerator))
r.denominator) in
string_of_nat nat) in
- if (round_futur_last_digit s 0 (String.length s))
+ if round_futur_last_digit (Bytes.unsafe_of_string s) 0
+ (String.length s)
then
let m = num_decimal_digits_int (succ msd) in
- let str = String.make (n + m + 4) '0' in
+ let str = Bytes.make (n + m + 4) '0' in
(String.blit (if sign_r = -1 then "-1." else "+1.") 0 str 0 3);
- String.set str !i ('e');
+ Bytes.set str !i ('e');
incr i;
(if m = 0
- then String.set str !i '0'
+ then Bytes.set str !i '0'
else String.blit (string_of_int (succ msd)) 0 str !i m);
- str
+ Bytes.unsafe_to_string str
else
let m = num_decimal_digits_int (succ msd)
and p = n + 3 in
- let str = String.make (succ (m + p)) '0' in
+ let str = Bytes.make (succ (m + p)) '0' in
(String.blit (if sign_r = -1 then "-0." else "+0.") 0 str 0 3);
(String.blit s 0 str 3 n);
- String.set str p 'e';
+ Bytes.set str p 'e';
(if m = 0
- then String.set str (succ p) '0'
+ then Bytes.set str (succ p) '0'
else (String.blit (string_of_int (succ msd)) 0 str (succ p) m));
- str
+ Bytes.unsafe_to_string str
(* String approximation of a rational with a fixed number of significant *)
(* digits printed *)
diff --git a/otherlibs/str/.depend b/otherlibs/str/.depend
index b0ff35895b..5be8377c2d 100644
--- a/otherlibs/str/.depend
+++ b/otherlibs/str/.depend
@@ -1,9 +1,9 @@
strstubs.o: strstubs.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/fail.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/fail.h
str.cmi :
str.cmo : str.cmi
str.cmx : str.cmi
diff --git a/otherlibs/str/str.ml b/otherlibs/str/str.ml
index b9b8c1536d..ffaea89ba4 100644
--- a/otherlibs/str/str.ml
+++ b/otherlibs/str/str.ml
@@ -25,16 +25,18 @@ let last_chars s n = String.sub s (String.length s - n) n
module Charset =
struct
- type t = string (* of length 32 *)
+ type t = bytes (* of length 32 *)
- (*let empty = String.make 32 '\000'*)
- let full = String.make 32 '\255'
+ (*let empty = Bytes.make 32 '\000'*)
+ let full = Bytes.make 32 '\255'
- let make_empty () = String.make 32 '\000'
+ let make_empty () = Bytes.make 32 '\000'
let add s c =
let i = Char.code c in
- s.[i lsr 3] <- Char.chr(Char.code s.[i lsr 3] lor (1 lsl (i land 7)))
+ Bytes.set s (i lsr 3)
+ (Char.chr (Char.code (Bytes.get s (i lsr 3))
+ lor (1 lsl (i land 7))))
let add_range s c1 c2 =
for i = Char.code c1 to Char.code c2 do add s (Char.chr i) done
@@ -46,23 +48,26 @@ module Charset =
let s = make_empty () in add_range s c1 c2; s
*)
let complement s =
- let r = String.create 32 in
+ let r = Bytes.create 32 in
for i = 0 to 31 do
- r.[i] <- Char.chr(Char.code s.[i] lxor 0xFF)
+ Bytes.set r i (Char.chr(Char.code (Bytes.get s i) lxor 0xFF))
done;
r
let union s1 s2 =
- let r = String.create 32 in
+ let r = Bytes.create 32 in
for i = 0 to 31 do
- r.[i] <- Char.chr(Char.code s1.[i] lor Char.code s2.[i])
+ Bytes.set r i (Char.chr(Char.code (Bytes.get s1 i)
+ lor Char.code (Bytes.get s2 i)))
done;
r
let disjoint s1 s2 =
try
for i = 0 to 31 do
- if Char.code s1.[i] land Char.code s2.[i] <> 0 then raise Exit
+ if Char.code (Bytes.get s1 i) land Char.code (Bytes.get s2 i)
+ <> 0
+ then raise Exit
done;
true
with Exit ->
@@ -70,7 +75,7 @@ module Charset =
let iter fn s =
for i = 0 to 31 do
- let c = Char.code s.[i] in
+ let c = Char.code (Bytes.get s i) in
if c <> 0 then
for j = 0 to 7 do
if c land (1 lsl j) <> 0 then fn (Char.chr ((i lsl 3) + j))
@@ -78,8 +83,8 @@ module Charset =
done
let expand s =
- let r = String.make 256 '\000' in
- iter (fun c -> r.[Char.code c] <- '\001') s;
+ let r = Bytes.make 256 '\000' in
+ iter (fun c -> Bytes.set r (Char.code c) '\001') s;
r
let fold_case s =
@@ -201,14 +206,14 @@ let charclass_of_regexp fold_case re =
| CharClass(cl, compl) -> (cl, compl)
| _ -> assert false in
let cl2 = if fold_case then Charset.fold_case cl1 else cl1 in
- if compl then Charset.complement cl2 else cl2
+ Bytes.to_string (if compl then Charset.complement cl2 else cl2)
(* The case fold table: maps characters to their lowercase equivalent *)
let fold_case_table =
- let t = String.create 256 in
- for i = 0 to 255 do t.[i] <- Char.lowercase(Char.chr i) done;
- t
+ let t = Bytes.create 256 in
+ for i = 0 to 255 do Bytes.set t i (Char.lowercase(Char.chr i)) done;
+ Bytes.to_string t
module StringMap =
Map.Make(struct type t = string let compare (x:t) y = compare x y end)
@@ -292,7 +297,7 @@ let compile fold_case re =
| CharClass(cl, compl) ->
let cl1 = if fold_case then Charset.fold_case cl else cl in
let cl2 = if compl then Charset.complement cl1 else cl1 in
- emit_instr op_CHARCLASS (cpool_index cl2)
+ emit_instr op_CHARCLASS (cpool_index (Bytes.to_string cl2))
| Seq rl ->
emit_seq_code rl
| Alt(r1, r2) ->
@@ -412,7 +417,7 @@ let compile fold_case re =
let start_pos =
if start = Charset.full
then -1
- else cpool_index (Charset.expand start') in
+ else cpool_index (Bytes.to_string (Charset.expand start')) in
let constantpool = Array.make !cpoolpos "" in
StringMap.iter (fun str idx -> constantpool.(idx) <- str) !cpool;
{ prog = Array.sub !prog 0 !progpos;
@@ -553,16 +558,19 @@ let regexp_case_fold e = compile true (parse e)
let quote s =
let len = String.length s in
- let buf = String.create (2 * len) in
+ let buf = Bytes.create (2 * len) in
let pos = ref 0 in
for i = 0 to len - 1 do
match s.[i] with
'[' | ']' | '*' | '.' | '\\' | '?' | '+' | '^' | '$' as c ->
- buf.[!pos] <- '\\'; buf.[!pos + 1] <- c; pos := !pos + 2
+ Bytes.set buf !pos '\\';
+ Bytes.set buf (!pos + 1) c;
+ pos := !pos + 2
| c ->
- buf.[!pos] <- c; pos := !pos + 1
+ Bytes.set buf !pos c;
+ pos := !pos + 1
done;
- String.sub buf 0 !pos
+ Bytes.sub_string buf 0 !pos
let regexp_string s = compile false (String s)
diff --git a/otherlibs/systhreads/.depend b/otherlibs/systhreads/.depend
index 93b01d6876..85add2e592 100644
--- a/otherlibs/systhreads/.depend
+++ b/otherlibs/systhreads/.depend
@@ -1,14 +1,14 @@
st_stubs.o: st_stubs.c ../../byterun/alloc.h \
- ../../byterun/compatibility.h ../../byterun/misc.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/backtrace.h ../../byterun/callback.h \
- ../../byterun/custom.h ../../byterun/fail.h ../../byterun/io.h \
- ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/misc.h \
- ../../byterun/mlvalues.h ../../byterun/printexc.h ../../byterun/roots.h \
- ../../byterun/memory.h ../../byterun/signals.h ../../byterun/stacks.h \
- ../../byterun/sys.h threads.h st_posix.h
+ ../../byterun/compatibility.h ../../byterun/misc.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/backtrace.h ../../byterun/callback.h \
+ ../../byterun/custom.h ../../byterun/fail.h ../../byterun/io.h \
+ ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/misc.h \
+ ../../byterun/mlvalues.h ../../byterun/printexc.h ../../byterun/roots.h \
+ ../../byterun/memory.h ../../byterun/signals.h ../../byterun/stacks.h \
+ ../../byterun/sys.h threads.h st_posix.h
condition.cmi : mutex.cmi
event.cmi :
mutex.cmi :
diff --git a/otherlibs/systhreads/Makefile b/otherlibs/systhreads/Makefile
index a34bd4b879..a08bf34b43 100644
--- a/otherlibs/systhreads/Makefile
+++ b/otherlibs/systhreads/Makefile
@@ -19,7 +19,7 @@ CAMLC=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/ocamlc -nostdlib \
CAMLOPT=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/ocamlopt -nostdlib \
-I $(ROOTDIR)/stdlib -I $(ROOTDIR)/otherlibs/unix
MKLIB=../../boot/ocamlrun ../../tools/ocamlmklib
-COMPFLAGS=-w +33..39 -warn-error A -g -bin-annot
+COMPFLAGS=-w +33..39 -warn-error A -g -bin-annot -safe-string
BYTECODE_C_OBJS=st_stubs_b.o
NATIVECODE_C_OBJS=st_stubs_n.o
diff --git a/otherlibs/systhreads/threadUnix.ml b/otherlibs/systhreads/threadUnix.ml
index 335afcb09e..c18f75bb47 100644
--- a/otherlibs/systhreads/threadUnix.ml
+++ b/otherlibs/systhreads/threadUnix.ml
@@ -26,6 +26,7 @@ let waitpid = Unix.waitpid
let system = Unix.system
let read = Unix.read
let write = Unix.write
+let write_substring = Unix.write_substring
let select = Unix.select
let timed_read fd buff ofs len timeout =
@@ -38,6 +39,9 @@ let timed_write fd buff ofs len timeout =
then Unix.write fd buff ofs len
else raise (Unix_error(ETIMEDOUT, "timed_write", ""))
+let timed_write_substring fd buff ofs len timeout =
+ timed_write fd (Bytes.unsafe_of_string buff) ofs len timeout
+
let pipe = Unix.pipe
let open_process_in = Unix.open_process_in
@@ -52,6 +56,8 @@ external connect : file_descr -> sockaddr -> unit = "unix_connect"
let recv = Unix.recv
let recvfrom = Unix.recvfrom
let send = Unix.send
+let send_substring = Unix.send_substring
let sendto = Unix.sendto
+let sendto_substring = Unix.sendto_substring
let open_connection = Unix.open_connection
diff --git a/otherlibs/systhreads/threadUnix.mli b/otherlibs/systhreads/threadUnix.mli
index 63d27335f5..cac796b925 100644
--- a/otherlibs/systhreads/threadUnix.mli
+++ b/otherlibs/systhreads/threadUnix.mli
@@ -30,24 +30,29 @@ val system : string -> Unix.process_status
(** {6 Basic input/output} *)
-val read : Unix.file_descr -> string -> int -> int -> int
-val write : Unix.file_descr -> string -> int -> int -> int
+val read : Unix.file_descr -> bytes -> int -> int -> int
+val write : Unix.file_descr -> bytes -> int -> int -> int
+val write_substring : Unix.file_descr -> string -> int -> int -> int
(** {6 Input/output with timeout} *)
val timed_read :
Unix.file_descr ->
- string -> int -> int -> float -> int
+ bytes -> int -> int -> float -> int
(** See {!ThreadUnix.timed_write}. *)
val timed_write :
Unix.file_descr ->
- string -> int -> int -> float -> int
+ bytes -> int -> int -> float -> int
(** Behave as {!ThreadUnix.read} and {!ThreadUnix.write}, except that
[Unix_error(ETIMEDOUT,_,_)] is raised if no data is
available for reading or ready for writing after [d] seconds.
The delay [d] is given in the fifth argument, in seconds. *)
+val timed_write_substring :
+ Unix.file_descr -> string -> int -> int -> float -> int
+(** See {!ThreadUnix.timed_write}. *)
+
(** {6 Polling} *)
val select :
@@ -72,12 +77,16 @@ val socket : Unix.socket_domain ->
Unix.socket_type -> int -> Unix.file_descr
val accept : Unix.file_descr -> Unix.file_descr * Unix.sockaddr
val connect : Unix.file_descr -> Unix.sockaddr -> unit
-val recv : Unix.file_descr -> string ->
+val recv : Unix.file_descr -> bytes ->
int -> int -> Unix.msg_flag list -> int
-val recvfrom : Unix.file_descr -> string -> int -> int ->
+val recvfrom : Unix.file_descr -> bytes -> int -> int ->
Unix.msg_flag list -> int * Unix.sockaddr
-val send : Unix.file_descr -> string -> int -> int ->
+val send : Unix.file_descr -> bytes -> int -> int ->
Unix.msg_flag list -> int
-val sendto : Unix.file_descr -> string -> int -> int ->
+val send_substring : Unix.file_descr -> string -> int -> int ->
+ Unix.msg_flag list -> int
+val sendto : Unix.file_descr -> bytes -> int -> int ->
+ Unix.msg_flag list -> Unix.sockaddr -> int
+val sendto_substring : Unix.file_descr -> string -> int -> int ->
Unix.msg_flag list -> Unix.sockaddr -> int
val open_connection : Unix.sockaddr -> in_channel * out_channel
diff --git a/otherlibs/threads/.depend b/otherlibs/threads/.depend
index 091feb6394..bc03050be3 100644
--- a/otherlibs/threads/.depend
+++ b/otherlibs/threads/.depend
@@ -1,14 +1,14 @@
scheduler.o: scheduler.c ../../byterun/alloc.h \
- ../../byterun/compatibility.h ../../byterun/misc.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/backtrace.h ../../byterun/callback.h \
- ../../byterun/config.h ../../byterun/fail.h ../../byterun/io.h \
- ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/misc.h \
- ../../byterun/mlvalues.h ../../byterun/printexc.h ../../byterun/roots.h \
- ../../byterun/memory.h ../../byterun/signals.h ../../byterun/stacks.h \
- ../../byterun/sys.h
+ ../../byterun/compatibility.h ../../byterun/misc.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/backtrace.h ../../byterun/callback.h \
+ ../../byterun/config.h ../../byterun/fail.h ../../byterun/io.h \
+ ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/misc.h \
+ ../../byterun/mlvalues.h ../../byterun/printexc.h ../../byterun/roots.h \
+ ../../byterun/memory.h ../../byterun/signals.h ../../byterun/stacks.h \
+ ../../byterun/sys.h
condition.cmi : mutex.cmi
event.cmi :
marshal.cmi :
diff --git a/otherlibs/threads/Makefile b/otherlibs/threads/Makefile
index 5c4be281da..1c4434f5b3 100644
--- a/otherlibs/threads/Makefile
+++ b/otherlibs/threads/Makefile
@@ -19,7 +19,7 @@ ROOTDIR=../..
CAMLC=$(ROOTDIR)/boot/ocamlrun $(ROOTDIR)/ocamlc -nostdlib \
-I $(ROOTDIR)/stdlib -I $(ROOTDIR)/otherlibs/unix
MKLIB=../../boot/ocamlrun ../../tools/ocamlmklib
-COMPFLAGS=-w +33..39 -warn-error A -bin-annot
+COMPFLAGS=-w +33..39 -warn-error A -bin-annot -safe-string
C_OBJS=scheduler.o
@@ -27,7 +27,7 @@ CAML_OBJS=thread.cmo mutex.cmo condition.cmo event.cmo threadUnix.cmo
LIB=../../stdlib
-LIB_OBJS=pervasives.cmo \
+LIB_OBJS=$(LIB)/camlinternalFormatBasics.cmo pervasives.cmo \
$(LIB)/array.cmo $(LIB)/list.cmo $(LIB)/char.cmo $(LIB)/string.cmo \
$(LIB)/sys.cmo $(LIB)/sort.cmo marshal.cmo $(LIB)/obj.cmo \
$(LIB)/int32.cmo $(LIB)/int64.cmo $(LIB)/nativeint.cmo \
diff --git a/otherlibs/threads/marshal.ml b/otherlibs/threads/marshal.ml
index c71ca83d08..005e964372 100644
--- a/otherlibs/threads/marshal.ml
+++ b/otherlibs/threads/marshal.ml
@@ -16,6 +16,9 @@ type extern_flags =
| Closures
| Compat_32
+external to_bytes: 'a -> extern_flags list -> bytes
+ = "caml_output_value_to_string"
+
external to_string: 'a -> extern_flags list -> string
= "caml_output_value_to_string"
@@ -23,35 +26,34 @@ let to_channel chan v flags =
output_string chan (to_string v flags)
external to_buffer_unsafe:
- string -> int -> int -> 'a -> extern_flags list -> int
+ bytes -> int -> int -> 'a -> extern_flags list -> int
= "caml_output_value_to_buffer"
let to_buffer buff ofs len v flags =
- if ofs < 0 || len < 0 || ofs + len > String.length buff
+ if ofs < 0 || len < 0 || ofs + len > Bytes.length buff
then invalid_arg "Marshal.to_buffer: substring out of bounds"
else to_buffer_unsafe buff ofs len v flags
-let to_buffer' ~buf ~pos ~len v ~mode = to_buffer buf pos len v mode
-
-external from_string_unsafe: string -> int -> 'a
+external from_channel: in_channel -> 'a = "caml_input_value"
+external from_bytes_unsafe: bytes -> int -> 'a
= "caml_input_value_from_string"
-external data_size_unsafe: string -> int -> int = "caml_marshal_data_size"
+external data_size_unsafe: bytes -> int -> int = "caml_marshal_data_size"
let header_size = 20
let data_size buff ofs =
- if ofs < 0 || ofs > String.length buff - header_size
+ if ofs < 0 || ofs > Bytes.length buff - header_size
then invalid_arg "Marshal.data_size"
else data_size_unsafe buff ofs
let total_size buff ofs = header_size + data_size buff ofs
-let from_string buff ofs =
- if ofs < 0 || ofs > String.length buff - header_size
- then invalid_arg "Marshal.from_size"
+let from_bytes buff ofs =
+ if ofs < 0 || ofs > Bytes.length buff - header_size
+ then invalid_arg "Marshal.from_bytes"
else begin
let len = data_size_unsafe buff ofs in
- if ofs > String.length buff - (header_size + len)
- then invalid_arg "Marshal.from_string"
- else from_string_unsafe buff ofs
+ if ofs > Bytes.length buff - (header_size + len)
+ then invalid_arg "Marshal.from_bytes"
+ else from_bytes_unsafe buff ofs
end
-let from_channel = Pervasives.input_value
+let from_string buff ofs = from_bytes (Bytes.unsafe_of_string buff) ofs
diff --git a/otherlibs/threads/pervasives.ml b/otherlibs/threads/pervasives.ml
index ef7432b875..e6f1cc16b9 100644
--- a/otherlibs/threads/pervasives.ml
+++ b/otherlibs/threads/pervasives.ml
@@ -50,9 +50,7 @@ external __MODULE__ : string = "%loc_MODULE"
external __POS__ : string * int * int * int = "%loc_POS"
external __LOC_OF__ : 'a -> string * 'a = "%loc_LOC"
-external __FILE_OF__ : 'a -> string * 'a = "%loc_FILE"
external __LINE_OF__ : 'a -> int * 'a = "%loc_LINE"
-external __MODULE_OF__ : 'a -> string * 'a = "%loc_MODULE"
external __POS_OF__ : 'a -> (string * int * int * int) * 'a = "%loc_POS"
(* Comparisons *)
@@ -87,7 +85,7 @@ 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 = "%mulint"
external ( / ) : int -> int -> int = "%divint"
external ( mod ) : int -> int -> int = "%modint"
@@ -168,19 +166,24 @@ type fpclass =
| FP_nan
external classify_float : float -> fpclass = "caml_classify_float"
-(* String operations -- more in module String *)
+(* String and byte sequence operations -- more in modules String and Bytes *)
external string_length : string -> int = "%string_length"
-external string_create : int -> string = "caml_create_string"
-external string_blit : string -> int -> string -> int -> int -> unit
+external bytes_length : bytes -> int = "%string_length"
+external bytes_create : int -> bytes = "caml_create_string"
+external string_blit : string -> int -> bytes -> int -> int -> unit
= "caml_blit_string" "noalloc"
+external bytes_blit : bytes -> int -> bytes -> int -> int -> unit
+ = "caml_blit_string" "noalloc"
+external bytes_unsafe_to_string : bytes -> string = "%identity"
+external bytes_unsafe_of_string : string -> bytes = "%identity"
let ( ^ ) s1 s2 =
let l1 = string_length s1 and l2 = string_length s2 in
- let s = string_create (l1 + l2) in
+ let s = bytes_create (l1 + l2) in
string_blit s1 0 s 0 l1;
string_blit s2 0 s l1 l2;
- s
+ bytes_unsafe_to_string s
(* Character operations -- more in module Char *)
@@ -223,12 +226,13 @@ let string_of_int n =
format_int "%d" n
external int_of_string : string -> int = "caml_int_of_string"
+external string_get : string -> int -> char = "%string_safe_get"
let valid_float_lexem s =
let l = string_length s in
let rec loop i =
if i >= l then s ^ "." else
- match s.[i] with
+ match string_get s i with
| '0' .. '9' | '-' -> loop (i + 1)
| _ -> s
in
@@ -319,7 +323,7 @@ let flush_all () =
iter l
in iter (out_channels_list ())
-external unsafe_output_partial : out_channel -> string -> int -> int -> int
+external unsafe_output_partial : out_channel -> bytes -> int -> int -> int
= "caml_ml_output_partial"
let rec unsafe_output oc buf pos len =
@@ -343,15 +347,19 @@ let rec output_char oc c =
with Sys_blocked_io ->
wait_outchan oc 1; output_char oc c
+let output_bytes oc s =
+ unsafe_output oc s 0 (bytes_length s)
+
let output_string oc s =
- unsafe_output oc s 0 (string_length s)
+ unsafe_output oc (bytes_unsafe_of_string s) 0 (string_length s)
let output oc s ofs len =
- if ofs < 0 || len < 0 || ofs > string_length s - len
+ if ofs < 0 || len < 0 || ofs > bytes_length s - len
then invalid_arg "output"
else unsafe_output oc s ofs len
-let output' oc ~buf ~pos ~len = output oc buf pos len
+let output_substring oc s ofs len =
+ output oc (bytes_unsafe_of_string s) ofs len
let rec output_byte oc b =
try
@@ -405,7 +413,7 @@ let rec input_char ic =
with Sys_blocked_io ->
wait_inchan ic; input_char ic
-external unsafe_input_blocking : in_channel -> string -> int -> int -> int
+external unsafe_input_blocking : in_channel -> bytes -> int -> int -> int
= "caml_ml_input"
let rec unsafe_input ic s ofs len =
@@ -415,7 +423,7 @@ let rec unsafe_input ic s ofs len =
wait_inchan ic; unsafe_input ic s ofs len
let input ic s ofs len =
- if ofs < 0 || len < 0 || ofs > string_length s - len
+ if ofs < 0 || len < 0 || ofs > bytes_length s - len
then invalid_arg "input"
else unsafe_input ic s ofs len
@@ -428,31 +436,38 @@ let rec unsafe_really_input ic s ofs len =
end
let really_input ic s ofs len =
- if ofs < 0 || len < 0 || ofs > string_length s - len
+ if ofs < 0 || len < 0 || ofs > bytes_length s - len
then invalid_arg "really_input"
else unsafe_really_input ic s ofs len
+let really_input_string ic len =
+ let s = bytes_create len in
+ really_input ic s 0 len;
+ bytes_unsafe_to_string s
+
+external bytes_set : bytes -> int -> char -> unit = "%string_safe_set"
+
let input_line ic =
- let buf = ref (string_create 128) in
+ let buf = ref (bytes_create 128) in
let pos = ref 0 in
begin try
while true do
- if !pos = string_length !buf then begin
- let newbuf = string_create (2 * !pos) in
- string_blit !buf 0 newbuf 0 !pos;
+ if !pos = bytes_length !buf then begin
+ let newbuf = bytes_create (2 * !pos) in
+ bytes_blit !buf 0 newbuf 0 !pos;
buf := newbuf
end;
let c = input_char ic in
if c = '\n' then raise Exit;
- !buf.[!pos] <- c;
+ bytes_set !buf !pos c;
incr pos
done
with Exit -> ()
| End_of_file -> if !pos = 0 then raise End_of_file
end;
- let res = string_create !pos in
- string_blit !buf 0 res 0 !pos;
- res
+ let res = bytes_create !pos in
+ bytes_blit !buf 0 res 0 !pos;
+ bytes_unsafe_to_string res
let rec input_byte ic =
try
@@ -468,15 +483,15 @@ let input_binary_int ic =
let b4 = input_byte ic in
(n1 lsl 24) + (b2 lsl 16) + (b3 lsl 8) + b4
-external unmarshal : string -> int -> 'a = "caml_input_value_from_string"
-external marshal_data_size : string -> int -> int = "caml_marshal_data_size"
+external unmarshal : bytes -> int -> 'a = "caml_input_value_from_string"
+external marshal_data_size : bytes -> int -> int = "caml_marshal_data_size"
let input_value ic =
- let header = string_create 20 in
+ let header = bytes_create 20 in
really_input ic header 0 20;
let bsize = marshal_data_size header 0 in
- let buffer = string_create (20 + bsize) in
- string_blit header 0 buffer 0 20;
+ let buffer = bytes_create (20 + bsize) in
+ bytes_blit header 0 buffer 0 20;
really_input ic buffer 20 bsize;
unmarshal buffer 0
@@ -492,6 +507,7 @@ external set_binary_mode_in : in_channel -> bool -> unit
let print_char c = output_char stdout c
let print_string s = output_string stdout s
+let print_bytes s = output_bytes stdout s
let print_int i = output_string stdout (string_of_int i)
let print_float f = output_string stdout (string_of_float f)
let print_endline s =
@@ -502,6 +518,7 @@ let print_newline () = output_char stdout '\n'; flush stdout
let prerr_char c = output_char stderr c
let prerr_string s = output_string stderr s
+let prerr_bytes s = output_bytes stderr s
let prerr_int i = output_string stderr (string_of_int i)
let prerr_float f = output_string stderr (string_of_float f)
let prerr_endline s =
@@ -528,33 +545,25 @@ module LargeFile =
end
(* Formats *)
+
+type ('a, 'b, 'c, 'd, 'e, 'f) format6
+ = ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.format6
+ = Format of ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.fmt
+ * string
+
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 (Format (fmt, str)) = str
+
external format_of_string :
('a, 'b, 'c, 'd, 'e, 'f) format6 ->
('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity"
-external format_to_string :
- ('a, 'b, 'c, 'd, 'e, 'f) format6 -> string = "%identity"
-external string_to_format :
- string -> ('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity"
-
-let (( ^^ ) :
- ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
- ('f, 'b, 'c, 'e, 'g, 'h) format6 ->
- ('a, 'b, 'c, 'd, 'g, 'h) format6) =
- fun fmt1 fmt2 ->
- string_to_format (format_to_string fmt1 ^ "%," ^ format_to_string fmt2)
-;;
-
-let string_of_format fmt =
- let s = format_to_string fmt in
- let l = string_length s in
- let r = string_create l in
- string_blit s 0 r 0 l;
- r
+let (^^) (Format (fmt1, str1)) (Format (fmt2, str2)) =
+ Format (CamlinternalFormatBasics.concat_fmt fmt1 fmt2,
+ str1 ^ "%," ^ str2)
(* Miscellaneous *)
diff --git a/otherlibs/threads/threadUnix.ml b/otherlibs/threads/threadUnix.ml
index fe5ef4fdfc..c086c1f55f 100644
--- a/otherlibs/threads/threadUnix.ml
+++ b/otherlibs/threads/threadUnix.ml
@@ -22,6 +22,8 @@ let system = Unix.system
let read = Unix.read
let write = Unix.write
let single_write = Unix.single_write
+let write_substring = Unix.write_substring
+let single_write_substring = Unix.single_write_substring
let select = Unix.select
let pipe = Unix.pipe
let open_process_in = Unix.open_process_in
@@ -36,7 +38,9 @@ let connect = Unix.connect
let recv = Unix.recv
let recvfrom = Unix.recvfrom
let send = Unix.send
+let send_substring = Unix.send_substring
let sendto = Unix.sendto
+let sendto_substring = Unix.sendto_substring
let open_connection = Unix.open_connection
let establish_server = Unix.establish_server
@@ -57,3 +61,6 @@ let rec timed_write fd buff ofs len timeout =
timed_write fd buff ofs len timeout
end
else raise (Unix_error(ETIMEDOUT, "timed_write", ""))
+
+let timed_write_substring fd buff ofs len timeout =
+ timed_write fd (Bytes.unsafe_of_string buff) ofs len timeout
diff --git a/otherlibs/threads/threadUnix.mli b/otherlibs/threads/threadUnix.mli
index 4ebe28f4f2..52862f98a1 100644
--- a/otherlibs/threads/threadUnix.mli
+++ b/otherlibs/threads/threadUnix.mli
@@ -30,21 +30,27 @@ val system : string -> Unix.process_status
(** {6 Basic input/output} *)
-val read : Unix.file_descr -> string -> int -> int -> int
-val write : Unix.file_descr -> string -> int -> int -> int
-val single_write : Unix.file_descr -> string -> int -> int -> int
+val read : Unix.file_descr -> bytes -> int -> int -> int
+val write : Unix.file_descr -> bytes -> int -> int -> int
+val single_write : Unix.file_descr -> bytes -> int -> int -> int
+val write_substring : Unix.file_descr -> string -> int -> int -> int
+val single_write_substring : Unix.file_descr -> string -> int -> int -> int
(** {6 Input/output with timeout} *)
-val timed_read : Unix.file_descr -> string -> int -> int -> float -> int
+val timed_read : Unix.file_descr -> bytes -> int -> int -> float -> int
(** See {!ThreadUnix.timed_write}. *)
-val timed_write : Unix.file_descr -> string -> int -> int -> float -> int
+val timed_write : Unix.file_descr -> bytes -> int -> int -> float -> int
(** Behave as {!ThreadUnix.read} and {!ThreadUnix.write}, except that
[Unix_error(ETIMEDOUT,_,_)] is raised if no data is
available for reading or ready for writing after [d] seconds.
The delay [d] is given in the fifth argument, in seconds. *)
+val timed_write_substring :
+ Unix.file_descr -> string -> int -> int -> float -> int
+(** See {!ThreadUnix.timed_write}. *)
+
(** {6 Polling} *)
val select :
@@ -74,13 +80,18 @@ val socketpair :
val accept : Unix.file_descr -> Unix.file_descr * Unix.sockaddr
val connect : Unix.file_descr -> Unix.sockaddr -> unit
val recv :
- Unix.file_descr -> string -> int -> int -> Unix.msg_flag list -> int
+ Unix.file_descr -> bytes -> int -> int -> Unix.msg_flag list -> int
val recvfrom :
- Unix.file_descr -> string -> int -> int -> Unix.msg_flag list ->
+ Unix.file_descr -> bytes -> int -> int -> Unix.msg_flag list ->
int * Unix.sockaddr
val send :
+ Unix.file_descr -> bytes -> int -> int -> Unix.msg_flag list -> int
+val send_substring :
Unix.file_descr -> string -> int -> int -> Unix.msg_flag list -> int
val sendto :
+ Unix.file_descr -> bytes -> int -> int -> Unix.msg_flag list ->
+ Unix.sockaddr -> int
+val sendto_substring :
Unix.file_descr -> string -> int -> int -> Unix.msg_flag list ->
Unix.sockaddr -> int
val open_connection : Unix.sockaddr -> in_channel * out_channel
diff --git a/otherlibs/threads/unix.ml b/otherlibs/threads/unix.ml
index 80ea7aed64..a397ec404f 100644
--- a/otherlibs/threads/unix.ml
+++ b/otherlibs/threads/unix.ml
@@ -205,15 +205,15 @@ external openfile : string -> open_flag list -> file_perm -> file_descr
= "unix_open"
external close : file_descr -> unit = "unix_close"
-external unsafe_read : file_descr -> string -> int -> int -> int = "unix_read"
-external unsafe_write : file_descr -> string -> int -> int -> int
+external unsafe_read : file_descr -> bytes -> int -> int -> int = "unix_read"
+external unsafe_write : file_descr -> bytes -> int -> int -> int
= "unix_write"
-external unsafe_single_write : file_descr -> string -> int -> int -> int
+external unsafe_single_write : file_descr -> bytes -> int -> int -> int
= "unix_single_write"
let rec read fd buf ofs len =
try
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.read"
else unsafe_read fd buf ofs len
with Unix_error((EAGAIN | EWOULDBLOCK), _, _) ->
@@ -221,7 +221,7 @@ let rec read fd buf ofs len =
let rec write fd buf ofs len =
try
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.write"
else unsafe_write fd buf ofs len
with Unix_error((EAGAIN | EWOULDBLOCK), _, _) ->
@@ -229,12 +229,18 @@ let rec write fd buf ofs len =
let rec single_write fd buf ofs len =
try
- if ofs < 0 || len < 0 || ofs > String.length buf - len
- then invalid_arg "Unix.partial_write"
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
+ then invalid_arg "Unix.single_write"
else unsafe_single_write fd buf ofs len
with Unix_error((EAGAIN | EWOULDBLOCK), _, _) ->
wait_write fd; single_write fd buf ofs len
+let write_substring fd buf ofs len =
+ write fd (Bytes.unsafe_of_string buf) ofs len
+
+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"
external out_channel_of_descr : file_descr -> out_channel
@@ -591,21 +597,21 @@ let connect s addr =
ignore(getpeername s)
external unsafe_recv :
- file_descr -> string -> int -> int -> msg_flag list -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> int
= "unix_recv"
external unsafe_recvfrom :
- file_descr -> string -> int -> int -> msg_flag list -> int * sockaddr
+ file_descr -> bytes -> int -> int -> msg_flag list -> int * sockaddr
= "unix_recvfrom"
external unsafe_send :
- file_descr -> string -> int -> int -> msg_flag list -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> int
= "unix_send"
external unsafe_sendto :
- file_descr -> string -> int -> int -> msg_flag list -> sockaddr -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> sockaddr -> int
= "unix_sendto" "unix_sendto_native"
let rec recv fd buf ofs len flags =
try
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.recv"
else unsafe_recv fd buf ofs len flags
with Unix_error((EAGAIN | EWOULDBLOCK), _, _) ->
@@ -613,7 +619,7 @@ let rec recv fd buf ofs len flags =
let rec recvfrom fd buf ofs len flags =
try
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.recvfrom"
else unsafe_recvfrom fd buf ofs len flags
with Unix_error((EAGAIN | EWOULDBLOCK), _, _) ->
@@ -622,7 +628,7 @@ let rec recvfrom fd buf ofs len flags =
let rec send fd buf ofs len flags =
try
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.send"
else unsafe_send fd buf ofs len flags
with Unix_error((EAGAIN | EWOULDBLOCK), _, _) ->
@@ -631,13 +637,19 @@ let rec send fd buf ofs len flags =
let rec sendto fd buf ofs len flags addr =
try
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.sendto"
else unsafe_sendto fd buf ofs len flags addr
with Unix_error((EAGAIN | EWOULDBLOCK), _, _) ->
wait_write fd;
sendto fd buf ofs len flags addr
+let send_substring fd buf ofs len flags =
+ send fd (Bytes.unsafe_of_string buf) ofs len flags
+
+let sendto_substring fd buf ofs len flags addr =
+ sendto fd (Bytes.unsafe_of_string buf) ofs len flags addr
+
type socket_bool_option =
SO_DEBUG
| SO_BROADCAST
diff --git a/otherlibs/unix/.depend b/otherlibs/unix/.depend
index f3f79821d1..63e1d22935 100644
--- a/otherlibs/unix/.depend
+++ b/otherlibs/unix/.depend
@@ -1,498 +1,502 @@
accept.o: accept.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
- socketaddr.h ../../byterun/misc.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
+ socketaddr.h ../../byterun/misc.h
access.o: access.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
addrofstr.o: addrofstr.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/fail.h \
- unixsupport.h socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/fail.h \
+ unixsupport.h socketaddr.h ../../byterun/misc.h
alarm.o: alarm.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
bind.o: bind.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h unixsupport.h socketaddr.h ../../byterun/misc.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h unixsupport.h socketaddr.h \
+ ../../byterun/misc.h
chdir.o: chdir.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
chmod.o: chmod.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
chown.o: chown.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
chroot.o: chroot.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
close.o: close.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/signals.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h \
+ ../../byterun/signals.h ../../byterun/mlvalues.h unixsupport.h
closedir.o: closedir.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
connect.o: connect.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h ../../byterun/signals.h unixsupport.h \
- socketaddr.h ../../byterun/misc.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h ../../byterun/signals.h unixsupport.h \
+ socketaddr.h ../../byterun/misc.h
cst2constr.o: cst2constr.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/fail.h ../../byterun/mlvalues.h \
- cst2constr.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/fail.h ../../byterun/mlvalues.h \
+ cst2constr.h
cstringv.o: cstringv.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h
dup.o: dup.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
dup2.o: dup2.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
envir.o: envir.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h
errmsg.o: errmsg.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h
execv.o: execv.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h
execve.o: execve.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h
execvp.o: execvp.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h
exit.o: exit.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
fchmod.o: fchmod.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h ../../byterun/signals.h unixsupport.h
fchown.o: fchown.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h ../../byterun/signals.h unixsupport.h
fcntl.o: fcntl.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h unixsupport.h
fork.o: fork.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h \
- ../../byterun/debugger.h ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h \
+ ../../byterun/debugger.h ../../byterun/mlvalues.h unixsupport.h
ftruncate.o: ftruncate.c ../../byterun/fail.h \
- ../../byterun/compatibility.h ../../byterun/misc.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h ../../byterun/io.h ../../byterun/signals.h \
- unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/misc.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h ../../byterun/io.h ../../byterun/signals.h \
+ unixsupport.h
getaddrinfo.o: getaddrinfo.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
- cst2constr.h socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
+ cst2constr.h socketaddr.h ../../byterun/misc.h
getcwd.o: getcwd.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/fail.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/fail.h unixsupport.h
getegid.o: getegid.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h unixsupport.h
geteuid.o: geteuid.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h unixsupport.h
getgid.o: getgid.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
getgr.o: getgr.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/fail.h \
- ../../byterun/mlvalues.h ../../byterun/alloc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/fail.h \
+ ../../byterun/mlvalues.h ../../byterun/alloc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h unixsupport.h
getgroups.o: getgroups.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h unixsupport.h
gethost.o: gethost.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
- socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
+ socketaddr.h ../../byterun/misc.h
gethostname.o: gethostname.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h unixsupport.h
getlogin.o: getlogin.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ unixsupport.h
getnameinfo.o: getnameinfo.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
- socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
+ socketaddr.h ../../byterun/misc.h
getpeername.o: getpeername.c ../../byterun/fail.h \
- ../../byterun/compatibility.h ../../byterun/misc.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h unixsupport.h socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/misc.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h unixsupport.h socketaddr.h \
+ ../../byterun/misc.h
getpid.o: getpid.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
getppid.o: getppid.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h unixsupport.h
getproto.o: getproto.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h unixsupport.h
getpw.o: getpw.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/fail.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/fail.h unixsupport.h
getserv.o: getserv.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h unixsupport.h
getsockname.o: getsockname.c ../../byterun/fail.h \
- ../../byterun/compatibility.h ../../byterun/misc.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h unixsupport.h socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/misc.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h unixsupport.h socketaddr.h \
+ ../../byterun/misc.h
gettimeofday.o: gettimeofday.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h unixsupport.h
getuid.o: getuid.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
gmtime.o: gmtime.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h unixsupport.h
initgroups.o: initgroups.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h unixsupport.h
isatty.o: isatty.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
itimer.o: itimer.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h unixsupport.h
kill.o: kill.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/fail.h \
- ../../byterun/mlvalues.h unixsupport.h ../../byterun/signals.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/fail.h \
+ ../../byterun/mlvalues.h unixsupport.h ../../byterun/signals.h
link.o: link.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
listen.o: listen.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h unixsupport.h
lockf.o: lockf.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h ../../byterun/signals.h unixsupport.h
lseek.o: lseek.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/io.h ../../byterun/signals.h \
- unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/io.h ../../byterun/signals.h \
+ unixsupport.h
mkdir.o: mkdir.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
mkfifo.o: mkfifo.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
nice.o: nice.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
open.o: open.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
opendir.o: opendir.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/alloc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/alloc.h \
+ ../../byterun/signals.h unixsupport.h
pipe.o: pipe.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h unixsupport.h
putenv.o: putenv.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/mlvalues.h unixsupport.h
read.o: read.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
readdir.o: readdir.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/fail.h ../../byterun/mlvalues.h \
- ../../byterun/alloc.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/fail.h ../../byterun/mlvalues.h \
+ ../../byterun/alloc.h ../../byterun/signals.h unixsupport.h
readlink.o: readlink.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/alloc.h \
- ../../byterun/fail.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/alloc.h \
+ ../../byterun/fail.h ../../byterun/signals.h unixsupport.h
rename.o: rename.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
rewinddir.o: rewinddir.c ../../byterun/fail.h \
- ../../byterun/compatibility.h ../../byterun/misc.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/misc.h \
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h unixsupport.h
rmdir.o: rmdir.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
select.o: select.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
sendrecv.o: sendrecv.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
- socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h \
+ socketaddr.h ../../byterun/misc.h
setgid.o: setgid.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
setgroups.o: setgroups.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h unixsupport.h
setsid.o: setsid.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h unixsupport.h
setuid.o: setuid.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
shutdown.o: shutdown.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h unixsupport.h
signals.o: signals.c ../../byterun/alloc.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/mlvalues.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/mlvalues.h \
+ ../../byterun/signals.h unixsupport.h
sleep.o: sleep.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/signals.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h \
+ ../../byterun/signals.h ../../byterun/mlvalues.h unixsupport.h
socket.o: socket.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h unixsupport.h
socketaddr.o: socketaddr.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h \
- socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/memory.h ../../byterun/gc.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h unixsupport.h \
+ socketaddr.h ../../byterun/misc.h
socketpair.o: socketpair.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h unixsupport.h
sockopt.o: sockopt.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/alloc.h \
- ../../byterun/fail.h unixsupport.h socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/alloc.h \
+ ../../byterun/fail.h unixsupport.h socketaddr.h ../../byterun/misc.h
stat.o: stat.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/alloc.h \
- ../../byterun/signals.h unixsupport.h cst2constr.h ../../byterun/io.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/alloc.h \
+ ../../byterun/signals.h unixsupport.h cst2constr.h ../../byterun/io.h
strofaddr.o: strofaddr.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h unixsupport.h socketaddr.h ../../byterun/misc.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h unixsupport.h socketaddr.h ../../byterun/misc.h
symlink.o: symlink.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
termios.o: termios.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/fail.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/fail.h unixsupport.h
time.o: time.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h unixsupport.h
times.o: times.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h unixsupport.h
truncate.o: truncate.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/fail.h \
- ../../byterun/signals.h ../../byterun/io.h unixsupport.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h ../../byterun/fail.h \
+ ../../byterun/signals.h ../../byterun/io.h unixsupport.h
umask.o: umask.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h unixsupport.h
unixsupport.o: unixsupport.c ../../byterun/mlvalues.h \
- ../../byterun/compatibility.h ../../byterun/config.h \
- ../../byterun/../config/m.h ../../byterun/../config/s.h \
- ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
- ../../byterun/callback.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/fail.h unixsupport.h cst2constr.h
+ ../../byterun/compatibility.h ../../byterun/config.h \
+ ../../byterun/../config/m.h ../../byterun/../config/s.h \
+ ../../byterun/misc.h ../../byterun/alloc.h ../../byterun/mlvalues.h \
+ ../../byterun/callback.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/fail.h unixsupport.h \
+ cst2constr.h
unlink.o: unlink.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
utimes.o: utimes.c ../../byterun/fail.h ../../byterun/compatibility.h \
- ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/mlvalues.h \
- ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
- ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/misc.h ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/mlvalues.h \
+ ../../byterun/mlvalues.h ../../byterun/memory.h ../../byterun/gc.h \
+ ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
wait.o: wait.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
- ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
- ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/alloc.h \
+ ../../byterun/mlvalues.h ../../byterun/fail.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/major_gc.h ../../byterun/freelist.h \
+ ../../byterun/minor_gc.h ../../byterun/signals.h unixsupport.h
write.o: write.c ../../byterun/mlvalues.h ../../byterun/compatibility.h \
- ../../byterun/config.h ../../byterun/../config/m.h \
- ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
- ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
- ../../byterun/freelist.h ../../byterun/minor_gc.h \
- ../../byterun/signals.h unixsupport.h
+ ../../byterun/config.h ../../byterun/../config/m.h \
+ ../../byterun/../config/s.h ../../byterun/misc.h ../../byterun/memory.h \
+ ../../byterun/gc.h ../../byterun/mlvalues.h ../../byterun/major_gc.h \
+ ../../byterun/freelist.h ../../byterun/minor_gc.h \
+ ../../byterun/signals.h unixsupport.h
unix.cmi :
unixLabels.cmi : unix.cmi
unix.cmo : unix.cmi
diff --git a/otherlibs/unix/unix.ml b/otherlibs/unix/unix.ml
index 8bd935f4cb..d18b338adb 100644
--- a/otherlibs/unix/unix.ml
+++ b/otherlibs/unix/unix.ml
@@ -237,27 +237,34 @@ external openfile : string -> open_flag list -> file_perm -> file_descr
= "unix_open"
external close : file_descr -> unit = "unix_close"
-external unsafe_read : file_descr -> string -> int -> int -> int = "unix_read"
-external unsafe_write : file_descr -> string -> int -> int -> int = "unix_write"
-external unsafe_single_write : file_descr -> string -> int -> int -> int
+external unsafe_read : file_descr -> bytes -> int -> int -> int
+ = "unix_read"
+external unsafe_write : file_descr -> bytes -> int -> int -> int = "unix_write"
+external unsafe_single_write : file_descr -> bytes -> int -> int -> int
= "unix_single_write"
let read fd buf ofs len =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.read"
else unsafe_read fd buf ofs len
let write fd buf ofs len =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.write"
else unsafe_write fd buf ofs len
(* write misbehaves because it attempts to write all data by making repeated
calls to the Unix write function (see comment in write.c and unix.mli).
- partial_write fixes this by never calling write twice. *)
+ single_write fixes this by never calling write twice. *)
let single_write fd buf ofs len =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.single_write"
else unsafe_single_write fd buf ofs len
+let write_substring fd buf ofs len =
+ write fd (Bytes.unsafe_of_string buf) ofs len
+
+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"
external out_channel_of_descr : file_descr -> out_channel
@@ -529,35 +536,41 @@ external getsockname : file_descr -> sockaddr = "unix_getsockname"
external getpeername : file_descr -> sockaddr = "unix_getpeername"
external unsafe_recv :
- file_descr -> string -> int -> int -> msg_flag list -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> int
= "unix_recv"
external unsafe_recvfrom :
- file_descr -> string -> int -> int -> msg_flag list -> int * sockaddr
+ file_descr -> bytes -> int -> int -> msg_flag list -> int * sockaddr
= "unix_recvfrom"
external unsafe_send :
- file_descr -> string -> int -> int -> msg_flag list -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> int
= "unix_send"
external unsafe_sendto :
- file_descr -> string -> int -> int -> msg_flag list -> sockaddr -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> sockaddr -> int
= "unix_sendto" "unix_sendto_native"
let recv fd buf ofs len flags =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.recv"
else unsafe_recv fd buf ofs len flags
let recvfrom fd buf ofs len flags =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.recvfrom"
else unsafe_recvfrom fd buf ofs len flags
let send fd buf ofs len flags =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.send"
else unsafe_send fd buf ofs len flags
let sendto fd buf ofs len flags addr =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.sendto"
else unsafe_sendto fd buf ofs len flags addr
+let send_substring fd buf ofs len flags =
+ send fd (Bytes.unsafe_of_string buf) ofs len flags
+
+let sendto_substring fd buf ofs len flags addr =
+ sendto fd (Bytes.unsafe_of_string buf) ofs len flags addr
+
type socket_bool_option =
SO_DEBUG
| SO_BROADCAST
diff --git a/otherlibs/unix/unix.mli b/otherlibs/unix/unix.mli
index efc3fe6fc4..59e5199357 100644
--- a/otherlibs/unix/unix.mli
+++ b/otherlibs/unix/unix.mli
@@ -259,23 +259,31 @@ val openfile : string -> open_flag list -> file_perm -> file_descr
val close : file_descr -> unit
(** Close a file descriptor. *)
-val read : file_descr -> string -> int -> int -> int
-(** [read fd buff ofs len] reads [len] characters from descriptor
- [fd], storing them in string [buff], starting at position [ofs]
- in string [buff]. Return the number of characters actually read. *)
-
-val write : file_descr -> string -> int -> int -> int
-(** [write fd buff ofs len] writes [len] characters to descriptor
- [fd], taking them from string [buff], starting at position [ofs]
- in string [buff]. Return the number of characters actually
- written. [write] repeats the writing operation until all characters
- have been written or an error occurs. *)
-
-val single_write : file_descr -> string -> int -> int -> int
+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
+ [buff]. Return the number of bytes actually read. *)
+
+val write : file_descr -> bytes -> int -> int -> int
+(** [write fd buff ofs len] writes [len] bytes to descriptor [fd],
+ taking them from byte sequence [buff], starting at position [ofs]
+ in [buff]. Return the number of bytes actually written. [write]
+ repeats the writing operation until all bytes have been written or
+ an error occurs. *)
+
+val single_write : file_descr -> bytes -> int -> int -> int
(** Same as [write], but attempts to write only once.
Thus, if an error occurs, [single_write] guarantees that no data
has been written. *)
+val write_substring : file_descr -> string -> int -> int -> int
+(** Same as [write], but take the data from a string instead of a byte
+ sequence. *)
+
+val single_write_substring : file_descr -> string -> int -> int -> int
+(** Same as [single_write], but take the data from a string instead of
+ a byte sequence. *)
+
(** {6 Interfacing with the standard input/output library} *)
@@ -994,20 +1002,28 @@ type msg_flag =
(** The flags for {!Unix.recv}, {!Unix.recvfrom},
{!Unix.send} and {!Unix.sendto}. *)
-val recv : file_descr -> string -> int -> int -> msg_flag list -> int
+val recv : file_descr -> bytes -> int -> int -> msg_flag list -> int
(** Receive data from a connected socket. *)
val recvfrom :
- file_descr -> string -> int -> int -> msg_flag list -> int * sockaddr
+ file_descr -> bytes -> int -> int -> msg_flag list -> int * sockaddr
(** Receive data from an unconnected socket. *)
-val send : file_descr -> string -> int -> int -> msg_flag list -> int
+val send : file_descr -> bytes -> int -> int -> msg_flag list -> int
(** Send data over a connected socket. *)
+val send_substring : file_descr -> string -> int -> int -> msg_flag list -> int
+(** Same as [send], but take the data from a string instead of a byte
+ sequence. *)
+
val sendto :
- file_descr -> string -> int -> int -> msg_flag list -> sockaddr -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> sockaddr -> int
(** Send data over an unconnected socket. *)
+val sendto_substring :
+ file_descr -> string -> int -> int -> msg_flag list -> sockaddr -> int
+(** Same as [sendto], but take the data from a string instead of a
+ byte sequence. *)
(** {6 Socket options} *)
diff --git a/otherlibs/unix/unixLabels.mli b/otherlibs/unix/unixLabels.mli
index 53e16b1d76..76ff890b12 100644
--- a/otherlibs/unix/unixLabels.mli
+++ b/otherlibs/unix/unixLabels.mli
@@ -261,23 +261,32 @@ val openfile : string -> mode:open_flag list -> perm:file_perm -> file_descr
val close : file_descr -> unit
(** Close a file descriptor. *)
-val read : file_descr -> buf:string -> pos:int -> len:int -> int
-(** [read fd buff ofs len] reads [len] characters from descriptor
- [fd], storing them in string [buff], starting at position [ofs]
- in string [buff]. Return the number of characters actually read. *)
-
-val write : file_descr -> buf:string -> pos:int -> len:int -> int
-(** [write fd buff ofs len] writes [len] characters to descriptor
- [fd], taking them from string [buff], starting at position [ofs]
- in string [buff]. Return the number of characters actually
- written. [write] repeats the writing operation until all characters
- have been written or an error occurs. *)
-
-val single_write : file_descr -> buf:string -> pos:int -> len:int -> int
+val read : file_descr -> buf:bytes -> pos:int -> len:int -> int
+(** [read fd buff ofs len] reads [len] bytes from descriptor [fd],
+ storing them in byte sequence [buff], starting at position [ofs] in
+ [buff]. Return the number of bytes actually read. *)
+
+val write : file_descr -> buf:bytes -> pos:int -> len:int -> int
+(** [write fd buff ofs len] writes [len] bytes to descriptor [fd],
+ taking them from byte sequence [buff], starting at position [ofs]
+ in [buff]. Return the number of bytes actually written. [write]
+ repeats the writing operation until all bytes have been written or
+ an error occurs. *)
+
+val single_write : file_descr -> buf:bytes -> pos:int -> len:int -> int
(** Same as [write], but attempts to write only once.
Thus, if an error occurs, [single_write] guarantees that no data
has been written. *)
+val write_substring : file_descr -> buf:string -> pos:int -> len:int -> int
+(** Same as [write], but take the data from a string instead of a byte
+ sequence. *)
+
+val single_write_substring :
+ file_descr -> buf:string -> pos:int -> len:int -> int
+(** Same as [single_write], but take the data from a string instead of
+ a byte sequence. *)
+
(** {6 Interfacing with the standard input/output library} *)
@@ -1000,23 +1009,34 @@ type msg_flag = Unix.msg_flag =
{!UnixLabels.send} and {!UnixLabels.sendto}. *)
val recv :
- file_descr -> buf:string -> pos:int -> len:int -> mode:msg_flag list -> int
+ file_descr -> buf:bytes -> pos:int -> len:int -> mode:msg_flag list -> int
(** Receive data from a connected socket. *)
val recvfrom :
- file_descr -> buf:string -> pos:int -> len:int -> mode:msg_flag list ->
+ file_descr -> buf:bytes -> pos:int -> len:int -> mode:msg_flag list ->
int * sockaddr
(** Receive data from an unconnected socket. *)
val send :
- file_descr -> buf:string -> pos:int -> len:int -> mode:msg_flag list -> int
+ file_descr -> buf:bytes -> pos:int -> len:int -> mode:msg_flag list -> int
(** Send data over a connected socket. *)
+val send_substring :
+ file_descr -> buf:string -> pos:int -> len:int -> mode:msg_flag list -> int
+(** Same as [send], but take the data from a string instead of a byte
+ sequence. *)
+
val sendto :
- file_descr -> buf:string -> pos:int -> len:int -> mode:msg_flag list ->
+ file_descr -> buf:bytes -> pos:int -> len:int -> mode:msg_flag list ->
addr:sockaddr -> int
(** Send data over an unconnected socket. *)
+val sendto_substring :
+ file_descr -> bug:string -> pos:int -> len:int -> mode:msg_flag list
+ -> sockaddr -> int
+(** Same as [sendto], but take the data from a string instead of a
+ byte sequence. *)
+
(** {6 Socket options} *)
diff --git a/otherlibs/win32unix/unix.ml b/otherlibs/win32unix/unix.ml
index 6c271ade2f..8866a2cd50 100644
--- a/otherlibs/win32unix/unix.ml
+++ b/otherlibs/win32unix/unix.ml
@@ -176,26 +176,32 @@ type file_perm = int
external openfile : string -> open_flag list -> file_perm -> file_descr
= "unix_open"
external close : file_descr -> unit = "unix_close"
-external unsafe_read : file_descr -> string -> int -> int -> int
+external unsafe_read : file_descr -> bytes -> int -> int -> int
= "unix_read"
-external unsafe_write : file_descr -> string -> int -> int -> int
+external unsafe_write : file_descr -> bytes -> int -> int -> int
= "unix_write"
-external unsafe_single_write : file_descr -> string -> int -> int -> int
+external unsafe_single_write : file_descr -> bytes -> int -> int -> int
= "unix_single_write"
let read fd buf ofs len =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.read"
else unsafe_read fd buf ofs len
let write fd buf ofs len =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.write"
else unsafe_write fd buf ofs len
let single_write fd buf ofs len =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.single_write"
else unsafe_single_write fd buf ofs len
+let write_substring fd buf ofs len =
+ write fd (Bytes.unsafe_of_string buf) ofs len
+
+let single_write_substring fd buf ofs len =
+ single_write fd (Bytes.unsafe_of_string buf) ofs len
+
(* Interfacing with the standard input/output library *)
external in_channel_of_descr: file_descr -> in_channel
@@ -535,35 +541,41 @@ external getsockname : file_descr -> sockaddr = "unix_getsockname"
external getpeername : file_descr -> sockaddr = "unix_getpeername"
external unsafe_recv :
- file_descr -> string -> int -> int -> msg_flag list -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> int
= "unix_recv"
external unsafe_recvfrom :
- file_descr -> string -> int -> int -> msg_flag list -> int * sockaddr
+ file_descr -> bytes -> int -> int -> msg_flag list -> int * sockaddr
= "unix_recvfrom"
external unsafe_send :
- file_descr -> string -> int -> int -> msg_flag list -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> int
= "unix_send"
external unsafe_sendto :
- file_descr -> string -> int -> int -> msg_flag list -> sockaddr -> int
+ file_descr -> bytes -> int -> int -> msg_flag list -> sockaddr -> int
= "unix_sendto" "unix_sendto_native"
let recv fd buf ofs len flags =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.recv"
else unsafe_recv fd buf ofs len flags
let recvfrom fd buf ofs len flags =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.recvfrom"
else unsafe_recvfrom fd buf ofs len flags
let send fd buf ofs len flags =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.send"
else unsafe_send fd buf ofs len flags
let sendto fd buf ofs len flags addr =
- if ofs < 0 || len < 0 || ofs > String.length buf - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buf - len
then invalid_arg "Unix.sendto"
else unsafe_sendto fd buf ofs len flags addr
+let send_substring fd buf ofs len flags =
+ send fd (Bytes.unsafe_of_string buf) ofs len flags
+
+let sendto_substring fd buf ofs len flags addr =
+ sendto fd (Bytes.unsafe_of_string buf) ofs len flags addr
+
type socket_bool_option =
SO_DEBUG
| SO_BROADCAST
diff --git a/parsing/ast_helper.ml b/parsing/ast_helper.ml
index bcc4d83653..f53cb29288 100644
--- a/parsing/ast_helper.ml
+++ b/parsing/ast_helper.ml
@@ -72,6 +72,7 @@ module Pat = struct
let type_ ?loc ?attrs a = mk ?loc ?attrs (Ppat_type a)
let lazy_ ?loc ?attrs a = mk ?loc ?attrs (Ppat_lazy a)
let unpack ?loc ?attrs a = mk ?loc ?attrs (Ppat_unpack a)
+ let exception_ ?loc ?attrs a = mk ?loc ?attrs (Ppat_exception a)
let extension ?loc ?attrs a = mk ?loc ?attrs (Ppat_extension a)
end
@@ -157,6 +158,7 @@ module Sig = struct
let value ?loc a = mk ?loc (Psig_value a)
let type_ ?loc a = mk ?loc (Psig_type 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 rec_module ?loc a = mk ?loc (Psig_recmodule a)
@@ -176,8 +178,8 @@ module Str = struct
let value ?loc a b = mk ?loc (Pstr_value (a, b))
let primitive ?loc a = mk ?loc (Pstr_primitive a)
let type_ ?loc a = mk ?loc (Pstr_type a)
+ let type_extension ?loc a = mk ?loc (Pstr_typext a)
let exception_ ?loc a = mk ?loc (Pstr_exception a)
- let exn_rebind ?loc a = mk ?loc (Pstr_exn_rebind a)
let module_ ?loc a = mk ?loc (Pstr_module a)
let rec_module ?loc a = mk ?loc (Pstr_recmodule a)
let modtype ?loc a = mk ?loc (Pstr_modtype a)
@@ -236,6 +238,7 @@ module Ctf = struct
let method_ ?loc ?attrs a b c d = mk ?loc ?attrs (Pctf_method (a, b, c, d))
let constraint_ ?loc ?attrs a b = mk ?loc ?attrs (Pctf_constraint (a, b))
let extension ?loc ?attrs a = mk ?loc ?attrs (Pctf_extension a)
+ let attribute ?loc a = mk ?loc (Pctf_attribute a)
end
module Cf = struct
@@ -253,6 +256,7 @@ module Cf = struct
let constraint_ ?loc ?attrs a b = mk ?loc ?attrs (Pcf_constraint (a, b))
let initializer_ ?loc ?attrs a = mk ?loc ?attrs (Pcf_initializer a)
let extension ?loc ?attrs a = mk ?loc ?attrs (Pcf_extension a)
+ let attribute ?loc a = mk ?loc (Pcf_attribute a)
let virtual_ ct = Cfk_virtual ct
let concrete o e = Cfk_concrete (o, e)
@@ -379,6 +383,43 @@ module Type = struct
}
end
+(** Type extensions *)
+module Te = struct
+ let mk ?(attrs = []) ?(params = []) ?(priv = Public) path constructors =
+ {
+ ptyext_path = path;
+ ptyext_params = params;
+ ptyext_constructors = constructors;
+ ptyext_private = priv;
+ ptyext_attributes = attrs;
+ }
+
+ let constructor ?(loc = !default_loc) ?(attrs = []) name kind =
+ {
+ pext_name = name;
+ pext_kind = kind;
+ pext_loc = loc;
+ pext_attributes = attrs;
+ }
+
+ let decl ?(loc = !default_loc) ?(attrs = []) ?(args = Pcstr_tuple []) ?res name =
+ {
+ pext_name = name;
+ pext_kind = Pext_decl(args, res);
+ pext_loc = loc;
+ pext_attributes = attrs;
+ }
+
+ let rebind ?(loc = !default_loc) ?(attrs = []) name lid =
+ {
+ pext_name = name;
+ pext_kind = Pext_rebind lid;
+ pext_loc = loc;
+ pext_attributes = attrs;
+ }
+end
+
+
module Csig = struct
let mk self fields =
{
@@ -394,84 +435,3 @@ module Cstr = struct
pcstr_fields = fields;
}
end
-
-module Exrb = struct
- let mk ?(loc = !default_loc) ?(attrs = []) name lid =
- {
- pexrb_name = name;
- pexrb_lid = lid;
- pexrb_attributes = attrs;
- pexrb_loc = loc;
- }
-end
-
-module Convenience = struct
- open Location
-
- let may_tuple tup = function
- | [] -> None
- | [x] -> Some x
- | l -> Some (tup ?loc:None ?attrs:None l)
-
- let lid s = mkloc (Longident.parse s) !default_loc
- let tuple l = Exp.tuple l
- let constr s args = Exp.construct (lid s) (may_tuple Exp.tuple args)
- let nil () = constr "[]" []
- let unit () = constr "()" []
- let cons hd tl = constr "::" [hd; tl]
- let list l = List.fold_right cons l (nil ())
- let str s = Exp.constant (Const_string (s, None))
- let int x = Exp.constant (Const_int x)
- let char x = Exp.constant (Const_char x)
- let float x = Exp.constant (Const_float (string_of_float x))
- let record ?over l =
- Exp.record (List.map (fun (s, e) -> (lid s, e)) l) over
- let func l = Exp.function_ (List.map (fun (p, e) -> Exp.case p e) l)
- let lam ?(label = "") ?default pat exp = Exp.fun_ label default pat exp
- let app f l = Exp.apply f (List.map (fun a -> "", a) l)
- let evar s = Exp.ident (lid s)
- let let_in ?(recursive = false) b body =
- Exp.let_ (if recursive then Recursive else Nonrecursive) b body
-
- let pvar s = Pat.var (mkloc s !default_loc)
- let pconstr s args = Pat.construct (lid s) (may_tuple Pat.tuple args)
- let precord ?(closed = Open) l =
- Pat.record (List.map (fun (s, e) -> (lid s, e)) l) closed
- let pnil () = pconstr "[]" []
- let pcons hd tl = pconstr "::" [hd; tl]
- let punit () = pconstr "()" []
- let plist l = List.fold_right pcons l (pnil ())
- let ptuple l = Pat.tuple l
-
- let pstr s = Pat.constant (Const_string (s, None))
- let pint x = Pat.constant (Const_int x)
- let pchar x = Pat.constant (Const_char x)
- let pfloat x = Pat.constant (Const_float (string_of_float x))
-
- let tconstr c l = Typ.constr (lid c) l
-
- let get_str = function
- | {pexp_desc=Pexp_constant (Const_string (s, _)); _} -> Some s
- | e -> None
-
- let get_lid = function
- | {pexp_desc=Pexp_ident{txt=id;_};_} ->
- Some (String.concat "." (Longident.flatten id))
- | _ -> None
-
- let find_attr s attrs =
- try Some (snd (List.find (fun (x, _) -> x.txt = s) attrs))
- with Not_found -> None
-
- let expr_of_payload = function
- | PStr [{pstr_desc=Pstr_eval(e, _)}] -> Some e
- | _ -> None
-
- let find_attr_expr s attrs =
- match find_attr s attrs with
- | Some e -> expr_of_payload e
- | None -> None
-
- let has_attr s attrs =
- find_attr s attrs <> None
-end
diff --git a/parsing/ast_helper.mli b/parsing/ast_helper.mli
index abf0cf9733..847d428f61 100644
--- a/parsing/ast_helper.mli
+++ b/parsing/ast_helper.mli
@@ -42,8 +42,9 @@ module Typ :
-> core_type
val tuple: ?loc:loc -> ?attrs:attrs -> core_type list -> core_type
val constr: ?loc:loc -> ?attrs:attrs -> lid -> core_type list -> core_type
- val object_: ?loc:loc -> ?attrs:attrs -> (string * core_type) list
- -> closed_flag -> core_type
+ val object_: ?loc:loc -> ?attrs:attrs ->
+ (string * attributes * core_type) list -> closed_flag ->
+ core_type
val class_: ?loc:loc -> ?attrs:attrs -> lid -> core_type list -> core_type
val alias: ?loc:loc -> ?attrs:attrs -> core_type -> string -> core_type
val variant: ?loc:loc -> ?attrs:attrs -> row_field list -> closed_flag
@@ -78,6 +79,7 @@ module Pat:
val type_: ?loc:loc -> ?attrs:attrs -> lid -> pattern
val lazy_: ?loc:loc -> ?attrs:attrs -> pattern -> pattern
val unpack: ?loc:loc -> ?attrs:attrs -> str -> pattern
+ val exception_: ?loc:loc -> ?attrs:attrs -> pattern -> pattern
val extension: ?loc:loc -> ?attrs:attrs -> extension -> pattern
end
@@ -102,22 +104,33 @@ module Exp:
val tuple: ?loc:loc -> ?attrs:attrs -> expression list -> expression
val construct: ?loc:loc -> ?attrs:attrs -> lid -> expression option
-> expression
- val variant: ?loc:loc -> ?attrs:attrs -> label -> expression option -> expression
- val record: ?loc:loc -> ?attrs:attrs -> (lid * expression) list -> expression option -> expression
+ val variant: ?loc:loc -> ?attrs:attrs -> label -> expression option
+ -> expression
+ val record: ?loc:loc -> ?attrs:attrs -> (lid * expression) list
+ -> expression option -> expression
val field: ?loc:loc -> ?attrs:attrs -> expression -> lid -> expression
- val setfield: ?loc:loc -> ?attrs:attrs -> expression -> lid -> expression -> expression
+ val setfield: ?loc:loc -> ?attrs:attrs -> expression -> lid -> expression
+ -> expression
val array: ?loc:loc -> ?attrs:attrs -> expression list -> expression
- val ifthenelse: ?loc:loc -> ?attrs:attrs -> expression -> expression -> expression option -> expression
- val sequence: ?loc:loc -> ?attrs:attrs -> expression -> expression -> expression
- val while_: ?loc:loc -> ?attrs:attrs -> expression -> expression -> expression
- val for_: ?loc:loc -> ?attrs:attrs -> pattern -> expression -> expression -> direction_flag -> expression -> expression
- val coerce: ?loc:loc -> ?attrs:attrs -> expression -> core_type option -> core_type -> expression
- val constraint_: ?loc:loc -> ?attrs:attrs -> expression -> core_type -> expression
+ val ifthenelse: ?loc:loc -> ?attrs:attrs -> expression -> expression
+ -> expression option -> expression
+ val sequence: ?loc:loc -> ?attrs:attrs -> expression -> expression
+ -> expression
+ val while_: ?loc:loc -> ?attrs:attrs -> expression -> expression
+ -> expression
+ val for_: ?loc:loc -> ?attrs:attrs -> pattern -> expression -> expression
+ -> direction_flag -> expression -> expression
+ val coerce: ?loc:loc -> ?attrs:attrs -> expression -> core_type option
+ -> core_type -> expression
+ val constraint_: ?loc:loc -> ?attrs:attrs -> expression -> core_type
+ -> expression
val send: ?loc:loc -> ?attrs:attrs -> expression -> string -> expression
val new_: ?loc:loc -> ?attrs:attrs -> lid -> expression
val setinstvar: ?loc:loc -> ?attrs:attrs -> str -> expression -> expression
- val override: ?loc:loc -> ?attrs:attrs -> (str * expression) list -> expression
- val letmodule: ?loc:loc -> ?attrs:attrs -> str -> module_expr -> expression -> expression
+ val override: ?loc:loc -> ?attrs:attrs -> (str * expression) list
+ -> expression
+ val letmodule: ?loc:loc -> ?attrs:attrs -> str -> module_expr -> expression
+ -> expression
val assert_: ?loc:loc -> ?attrs:attrs -> expression -> expression
val lazy_: ?loc:loc -> ?attrs:attrs -> expression -> expression
val poly: ?loc:loc -> ?attrs:attrs -> expression -> core_type option -> expression
@@ -139,12 +152,23 @@ module Val:
(** Type declarations *)
module Type:
sig
- val mk: ?loc:loc -> ?attrs:attrs -> ?params:(str option * variance) list -> ?cstrs:(core_type * core_type * loc) list -> ?kind:type_kind -> ?priv:private_flag -> ?manifest:core_type -> str -> type_declaration
+ val mk: ?loc:loc -> ?attrs:attrs -> ?params:(core_type * variance) list -> ?cstrs:(core_type * core_type * loc) list -> ?kind:type_kind -> ?priv:private_flag -> ?manifest:core_type -> str -> type_declaration
val constructor: ?loc:loc -> ?attrs:attrs -> ?args:constructor_arguments -> ?res:core_type -> str -> constructor_declaration
val field: ?loc:loc -> ?attrs:attrs -> ?mut:mutable_flag -> str -> core_type -> label_declaration
end
+(** Type extensions *)
+module Te:
+ sig
+ val mk: ?attrs:attrs -> ?params:(core_type * variance) list -> ?priv:private_flag -> lid -> extension_constructor list -> type_extension
+
+ val constructor: ?loc:loc -> ?attrs:attrs -> str -> extension_constructor_kind -> extension_constructor
+
+ val decl: ?loc:loc -> ?attrs:attrs -> ?args:constructor_arguments -> ?res:core_type -> str -> extension_constructor
+ val rebind: ?loc:loc -> ?attrs:attrs -> str -> lid -> extension_constructor
+ end
+
(** {2 Module language} *)
(** Module type expressions *)
@@ -186,7 +210,8 @@ module Sig:
val value: ?loc:loc -> value_description -> signature_item
val type_: ?loc:loc -> type_declaration list -> signature_item
- val exception_: ?loc:loc -> constructor_declaration -> signature_item
+ val type_extension: ?loc:loc -> type_extension -> signature_item
+ val exception_: ?loc:loc -> extension_constructor -> signature_item
val module_: ?loc:loc -> module_declaration -> signature_item
val rec_module: ?loc:loc -> module_declaration list -> signature_item
val modtype: ?loc:loc -> module_type_declaration -> signature_item
@@ -207,8 +232,8 @@ module Str:
val value: ?loc:loc -> rec_flag -> value_binding list -> structure_item
val primitive: ?loc:loc -> value_description -> structure_item
val type_: ?loc:loc -> type_declaration list -> structure_item
- val exception_: ?loc:loc -> constructor_declaration -> structure_item
- val exn_rebind: ?loc:loc -> exception_rebind -> structure_item
+ val type_extension: ?loc:loc -> type_extension -> structure_item
+ val exception_: ?loc:loc -> extension_constructor -> 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
@@ -283,6 +308,7 @@ module Ctf:
val method_: ?loc:loc -> ?attrs:attrs -> string -> private_flag -> virtual_flag -> core_type -> class_type_field
val constraint_: ?loc:loc -> ?attrs:attrs -> core_type -> core_type -> class_type_field
val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_type_field
+ val attribute: ?loc:loc -> attribute -> class_type_field
end
(** Class expressions *)
@@ -312,6 +338,7 @@ module Cf:
val constraint_: ?loc:loc -> ?attrs:attrs -> core_type -> core_type -> class_field
val initializer_: ?loc:loc -> ?attrs:attrs -> expression -> class_field
val extension: ?loc:loc -> ?attrs:attrs -> extension -> class_field
+ val attribute: ?loc:loc -> attribute -> class_field
val virtual_: core_type -> class_field_kind
val concrete: override_flag -> expression -> class_field_kind
@@ -320,7 +347,7 @@ module Cf:
(** Classes *)
module Ci:
sig
- val mk: ?loc:loc -> ?attrs:attrs -> ?virt:virtual_flag -> ?params:(str * variance) list -> str -> 'a -> 'a class_infos
+ val mk: ?loc:loc -> ?attrs:attrs -> ?virt:virtual_flag -> ?params:(core_type * variance) list -> str -> 'a -> 'a class_infos
end
(** Class signatures *)
@@ -334,77 +361,3 @@ module Cstr:
sig
val mk: pattern -> class_field list -> class_structure
end
-
-(** Exception rebinding *)
-module Exrb:
- sig
- val mk: ?loc:loc -> ?attrs:attrs -> str -> lid -> exception_rebind
-end
-
-
-(** {2 Convenience functions} *)
-
-(** Convenience functions to help build and deconstruct AST fragments. *)
-module Convenience :
- sig
-
- (** {2 Misc} *)
-
- val lid: string -> lid
-
- (** {2 Expressions} *)
-
- val evar: string -> expression
- val let_in: ?recursive:bool -> value_binding list -> expression -> expression
-
- val constr: string -> expression list -> expression
- val record: ?over:expression -> (string * expression) list -> expression
- val tuple: expression list -> expression
-
- val nil: unit -> expression
- val cons: expression -> expression -> expression
- val list: expression list -> expression
-
- val unit: unit -> expression
-
- val func: (pattern * expression) list -> expression
- val lam: ?label:string -> ?default:expression -> pattern -> expression -> expression
- val app: expression -> expression list -> expression
-
- val str: string -> expression
- val int: int -> expression
- val char: char -> expression
- val float: float -> expression
-
- (** {2 Patterns} *)
-
- val pvar: string -> pattern
- val pconstr: string -> pattern list -> pattern
- val precord: ?closed:closed_flag -> (string * pattern) list -> pattern
- val ptuple: pattern list -> pattern
-
- val pnil: unit -> pattern
- val pcons: pattern -> pattern -> pattern
- val plist: pattern list -> pattern
-
- val pstr: string -> pattern
- val pint: int -> pattern
- val pchar: char -> pattern
- val pfloat: float -> pattern
-
- val punit: unit -> pattern
-
-
- (** {2 Types} *)
-
- val tconstr: string -> core_type list -> core_type
-
- (** {2 AST deconstruction} *)
-
- val get_str: expression -> string option
- val get_lid: expression -> string option
-
- val has_attr: string -> attributes -> bool
- val find_attr: string -> attributes -> payload option
- val find_attr_expr: string -> attributes -> expression option
- end
diff --git a/parsing/ast_mapper.ml b/parsing/ast_mapper.ml
index 4d05bf077f..aa6608a995 100644
--- a/parsing/ast_mapper.ml
+++ b/parsing/ast_mapper.ml
@@ -18,6 +18,8 @@
*)
+open Asttypes
+open Longident
open Parsetree
open Ast_helper
open Location
@@ -39,9 +41,10 @@ type mapper = {
class_type_field: mapper -> class_type_field -> class_type_field;
constructor_declaration: mapper -> constructor_declaration
-> constructor_declaration;
- exception_rebind: mapper -> exception_rebind -> exception_rebind;
expr: mapper -> expression -> expression;
extension: mapper -> extension -> extension;
+ extension_constructor: mapper -> extension_constructor
+ -> extension_constructor;
include_declaration: mapper -> include_declaration -> include_declaration;
include_description: mapper -> include_description -> include_description;
label_declaration: mapper -> label_declaration -> label_declaration;
@@ -61,6 +64,7 @@ type mapper = {
structure_item: mapper -> structure_item -> structure_item;
typ: mapper -> core_type -> core_type;
type_declaration: mapper -> type_declaration -> type_declaration;
+ type_extension: mapper -> type_extension -> type_extension;
type_kind: mapper -> type_kind -> type_kind;
value_binding: mapper -> value_binding -> value_binding;
value_description: mapper -> value_description -> value_description;
@@ -79,7 +83,8 @@ module T = struct
(* Type expressions for the core language *)
let row_field sub = function
- | Rtag (l, b, tl) -> Rtag (l, b, List.map (sub.typ sub) tl)
+ | Rtag (l, attrs, b, tl) ->
+ Rtag (l, sub.attributes sub attrs, b, List.map (sub.typ sub) tl)
| Rinherit t -> Rinherit (sub.typ sub t)
let map sub {ptyp_desc = desc; ptyp_loc = loc; ptyp_attributes = attrs} =
@@ -95,7 +100,8 @@ module T = struct
| Ptyp_constr (lid, tl) ->
constr ~loc ~attrs (map_loc sub lid) (List.map (sub.typ sub) tl)
| Ptyp_object (l, o) ->
- object_ ~loc ~attrs (List.map (map_snd (sub.typ sub)) l) o
+ let f (s, a, t) = (s, sub.attributes sub a, sub.typ sub t) in
+ object_ ~loc ~attrs (List.map f l) o
| Ptyp_class (lid, tl) ->
class_ ~loc ~attrs (map_loc sub lid) (List.map (sub.typ sub) tl)
| Ptyp_alias (t, s) -> alias ~loc ~attrs (sub.typ sub t) s
@@ -115,7 +121,7 @@ module T = struct
ptype_attributes;
ptype_loc} =
Type.mk (map_loc sub ptype_name)
- ~params:(List.map (map_fst (map_opt (map_loc sub))) ptype_params)
+ ~params:(List.map (map_fst (sub.typ sub)) ptype_params)
~priv:ptype_private
~cstrs:(List.map
(map_tuple3 (sub.typ sub) (sub.typ sub) (sub.location sub))
@@ -130,6 +136,42 @@ module T = struct
| Ptype_variant l ->
Ptype_variant (List.map (sub.constructor_declaration sub) l)
| Ptype_record l -> Ptype_record (List.map (sub.label_declaration sub) l)
+ | Ptype_open -> Ptype_open
+
+ let map_constructor_arguments sub = function
+ | Pcstr_tuple l -> Pcstr_tuple (List.map (sub.typ sub) l)
+ | Pcstr_record l ->
+ Pcstr_record (List.map (sub.label_declaration sub) l)
+
+ let map_type_extension sub
+ {ptyext_path; ptyext_params;
+ ptyext_constructors;
+ ptyext_private;
+ ptyext_attributes} =
+ Te.mk
+ (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_extension_constructor_kind sub = function
+ Pext_decl(ctl, cto) ->
+ Pext_decl(map_constructor_arguments sub ctl, map_opt (sub.typ sub) cto)
+ | Pext_rebind li ->
+ Pext_rebind (map_loc sub li)
+
+ let map_extension_constructor sub
+ {pext_name;
+ pext_kind;
+ pext_loc;
+ pext_attributes} =
+ Te.constructor
+ (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
module CT = struct
@@ -156,6 +198,7 @@ module CT = struct
| Pctf_method (s, p, v, t) -> method_ ~loc ~attrs s p v (sub.typ sub t)
| Pctf_constraint (t1, t2) ->
constraint_ ~loc ~attrs (sub.typ sub t1) (sub.typ sub t2)
+ | Pctf_attribute x -> attribute ~loc (sub.attribute sub x)
| Pctf_extension x -> extension ~loc ~attrs (sub.extension sub x)
let map_signature sub {pcsig_self; pcsig_fields} =
@@ -200,7 +243,8 @@ module MT = struct
match desc with
| Psig_value vd -> value ~loc (sub.value_description sub vd)
| Psig_type l -> type_ ~loc (List.map (sub.type_declaration sub) l)
- | Psig_exception ed -> exception_ ~loc (sub.constructor_declaration sub ed)
+ | Psig_typext te -> type_extension ~loc (sub.type_extension sub te)
+ | Psig_exception ed -> exception_ ~loc (sub.extension_constructor sub ed)
| Psig_module x -> module_ ~loc (sub.module_declaration sub x)
| Psig_recmodule l ->
rec_module ~loc (List.map (sub.module_declaration sub) l)
@@ -247,8 +291,8 @@ module M = struct
| 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 l -> type_ ~loc (List.map (sub.type_declaration sub) l)
- | Pstr_exception ed -> exception_ ~loc (sub.constructor_declaration sub ed)
- | Pstr_exn_rebind x -> exn_rebind ~loc (sub.exception_rebind sub x)
+ | Pstr_typext te -> type_extension ~loc (sub.type_extension sub te)
+ | Pstr_exception ed -> exception_ ~loc (sub.extension_constructor 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)
@@ -362,6 +406,7 @@ module P = struct
| Ppat_type s -> type_ ~loc ~attrs (map_loc sub s)
| Ppat_lazy p -> lazy_ ~loc ~attrs (sub.pat sub p)
| Ppat_unpack s -> unpack ~loc ~attrs (map_loc sub s)
+ | Ppat_exception p -> exception_ ~loc ~attrs (sub.pat sub p)
| Ppat_extension x -> extension ~loc ~attrs (sub.extension sub x)
end
@@ -406,6 +451,7 @@ module CE = struct
| Pcf_constraint (t1, t2) ->
constraint_ ~loc ~attrs (sub.typ sub t1) (sub.typ sub t2)
| Pcf_initializer e -> initializer_ ~loc ~attrs (sub.expr sub e)
+ | Pcf_attribute x -> attribute ~loc (sub.attribute sub x)
| Pcf_extension x -> extension ~loc ~attrs (sub.extension sub x)
let map_structure sub {pcstr_self; pcstr_fields} =
@@ -417,8 +463,8 @@ module CE = struct
let class_infos sub f {pci_virt; pci_params = pl; pci_name; pci_expr;
pci_loc; pci_attributes} =
Ci.mk
- ~virt:pci_virt
- ~params:(List.map (map_fst (map_loc sub)) pl)
+ ~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)
@@ -453,7 +499,8 @@ let default_mapper =
type_declaration = T.map_type_declaration;
type_kind = T.map_type_kind;
typ = T.map;
-
+ type_extension = T.map_type_extension;
+ extension_constructor = T.map_extension_constructor;
value_description =
(fun this {pval_name; pval_type; pval_prim; pval_loc;
pval_attributes} ->
@@ -530,12 +577,7 @@ let default_mapper =
constructor_declaration =
(fun this {pcd_name; pcd_args; pcd_res; pcd_loc; pcd_attributes} ->
- let args =
- match pcd_args with
- | Pcstr_tuple l -> Pcstr_tuple (List.map (this.typ this) l)
- | Pcstr_record l ->
- Pcstr_record (List.map (this.label_declaration this) l)
- in
+ let args = T.map_constructor_arguments this pcd_args in
Type.constructor
(map_loc this pcd_name)
~args
@@ -554,15 +596,6 @@ let default_mapper =
~attrs:(this.attributes this pld_attributes)
);
- exception_rebind =
- (fun this {pexrb_name; pexrb_lid; pexrb_attributes; pexrb_loc} ->
- Exrb.mk
- (map_loc this pexrb_name)
- (map_loc this pexrb_lid)
- ~loc:(this.location this pexrb_loc)
- ~attrs:(this.attributes this pexrb_attributes)
- );
-
cases = (fun this l -> List.map (this.case this) l);
case =
(fun this {pc_lhs; pc_guard; pc_rhs} ->
@@ -588,23 +621,134 @@ let default_mapper =
);
}
+let rec extension_of_error {loc; msg; if_highlight; sub} =
+ { loc; txt = "ocaml.error" },
+ PStr ([Str.eval (Exp.constant (Const_string (msg, None)));
+ Str.eval (Exp.constant (Const_string (if_highlight, None)))] @
+ (List.map (fun ext -> Str.extension (extension_of_error ext)) sub))
+
+let attribute_of_warning loc s =
+ { loc; txt = "ocaml.ppwarning" },
+ PStr ([Str.eval ~loc (Exp.constant (Const_string (s, None)))])
+let tool_name_ref = ref "_none_"
+
+let tool_name () = !tool_name_ref
+
+let restore_ppx_context payload =
+ let fields =
+ match payload with
+ | PStr [{pstr_desc = Pstr_eval
+ ({ pexp_desc = Pexp_record (fields, None) }, [])}] ->
+ fields
+ | _ ->
+ raise_errorf "Internal error: invalid [@@@ocaml.ppx.context] syntax"
+ in
+ let field name payload =
+ let rec get_string = function
+ | { pexp_desc = Pexp_constant (Const_string (str, None)) } -> str
+ | _ ->
+ raise_errorf
+ "Internal error: invalid [@@@ocaml.ppx.context { %s }] string syntax"
+ name
+ and get_bool pexp =
+ match pexp with
+ | {pexp_desc = Pexp_construct ({txt = Longident.Lident "true"}, None)} ->
+ true
+ | {pexp_desc = Pexp_construct ({txt = Longident.Lident "false"}, None)} ->
+ false
+ | _ ->
+ raise_errorf
+ "Internal error: invalid [@@@ocaml.ppx.context { %s }] bool syntax"
+ name
+ and get_list elem = function
+ | {pexp_desc =
+ Pexp_construct ({txt = Longident.Lident "::"},
+ Some {pexp_desc = Pexp_tuple [exp; rest]}) } ->
+ elem exp :: get_list elem rest
+ | {pexp_desc =
+ Pexp_construct ({txt = Longident.Lident "[]"}, None)} ->
+ []
+ | _ ->
+ raise_errorf
+ "Internal error: invalid [@@@ocaml.ppx.context { %s }] list syntax"
+ name
+ and get_option elem = function
+ | { pexp_desc =
+ Pexp_construct ({ txt = Longident.Lident "Some" }, Some exp) } ->
+ Some (elem exp)
+ | { pexp_desc =
+ Pexp_construct ({ txt = Longident.Lident "None" }, None) } ->
+ None
+ | _ ->
+ raise_errorf
+ "Internal error: invalid [@@@ocaml.ppx.context { %s }] option syntax"
+ name
+ in
+ match name with
+ | "tool_name" ->
+ tool_name_ref := get_string payload
+ | "include_dirs" ->
+ Clflags.include_dirs := get_list get_string payload
+ | "load_path" ->
+ Config.load_path := get_list get_string payload
+ | "open_modules" ->
+ Clflags.open_modules := get_list get_string payload
+ | "for_package" ->
+ Clflags.for_package := get_option get_string payload
+ | "debug" ->
+ Clflags.debug := get_bool payload
+ | _ ->
+ ()
+ in
+ List.iter (function ({txt=Lident name}, x) -> field name x | _ -> ()) fields
let apply ~source ~target mapper =
let ic = open_in_bin source in
- let magic = String.create (String.length Config.ast_impl_magic_number) in
- really_input ic magic 0 (String.length magic);
+ let magic =
+ really_input_string ic (String.length Config.ast_impl_magic_number)
+ in
if magic <> Config.ast_impl_magic_number
&& magic <> Config.ast_intf_magic_number then
- failwith "Ast_mapper: unknown magic number";
+ failwith "Ast_mapper: OCaml version mismatch or malformed input";
Location.input_name := input_value ic;
let ast = input_value ic in
close_in ic;
+ let implem ast =
+ try
+ begin match ast with
+ | {pstr_desc = Pstr_attribute ({txt = "ocaml.ppx.context"}, x)} :: _ ->
+ restore_ppx_context x
+ | _ -> ()
+ end;
+ mapper.structure mapper ast
+ with exn ->
+ match error_of_exn exn with
+ | Some error ->
+ [{pstr_desc = Pstr_extension (extension_of_error error, []);
+ pstr_loc = Location.none}]
+ | None -> raise exn
+ in
+ let iface ast =
+ try
+ begin match ast with
+ | {psig_desc = Psig_attribute ({txt = "ocaml.ppx.context"}, x)} :: _ ->
+ restore_ppx_context x
+ | _ -> ()
+ end;
+ mapper.signature mapper ast
+ with exn ->
+ match error_of_exn exn with
+ | Some error ->
+ [{psig_desc = Psig_extension (extension_of_error error, []);
+ psig_loc = Location.none}]
+ | None -> raise exn
+ in
let ast =
if magic = Config.ast_impl_magic_number
- then Obj.magic (mapper.structure mapper (Obj.magic ast))
- else Obj.magic (mapper.signature mapper (Obj.magic ast))
+ then Obj.magic (implem (Obj.magic ast))
+ else Obj.magic (iface (Obj.magic ast))
in
let oc = open_out_bin target in
output_string oc magic;
@@ -617,18 +761,57 @@ let run_main mapper =
let a = Sys.argv in
let n = Array.length a in
if n > 2 then
- apply ~source:a.(n - 2) ~target:a.(n - 1)
- (mapper (Array.to_list (Array.sub a 1 (n - 3))))
+ let mapper =
+ try mapper (Array.to_list (Array.sub a 1 (n - 3)))
+ with exn ->
+ (* PR #6463 *)
+ let f _ _ = raise exn in
+ {default_mapper with structure = f; signature = f}
+ in
+ apply ~source:a.(n - 2) ~target:a.(n - 1) mapper
else begin
Printf.eprintf "Usage: %s [extra_args] <infile> <outfile>\n%!"
Sys.executable_name;
exit 2
end
with exn ->
- begin try Location.report_exception Format.err_formatter exn
- with exn -> prerr_endline (Printexc.to_string exn)
- end;
+ prerr_endline (Printexc.to_string exn);
exit 2
let register_function = ref (fun _name f -> run_main f)
let register name f = !register_function name f
+
+
+let ppx_context ~tool_name () =
+ let open Longident in
+ let open Asttypes in
+ let open Ast_helper in
+ let lid name = { txt = Lident name; loc = Location.none } in
+ let make_string x = Exp.constant (Const_string (x, None)) in
+ let make_bool x =
+ if x
+ then Exp.construct (lid "true") None
+ else Exp.construct (lid "false") None
+ in
+ let rec make_list f lst =
+ match lst with
+ | x :: rest ->
+ Exp.construct (lid "::") (Some (Exp.tuple [f x; make_list f rest]))
+ | [] ->
+ Exp.construct (lid "[]") None
+ in
+ let make_option f opt =
+ match opt with
+ | Some x -> Exp.construct (lid "Some") (Some (f x))
+ | None -> Exp.construct (lid "None") None
+ in
+ { txt = "ocaml.ppx.context"; loc = Location.none },
+ Parsetree.PStr [Str.eval (
+ Exp.record ([
+ 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 "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;
+ ]) None)]
diff --git a/parsing/ast_mapper.mli b/parsing/ast_mapper.mli
index f8d3311e52..786c37d6be 100644
--- a/parsing/ast_mapper.mli
+++ b/parsing/ast_mapper.mli
@@ -33,9 +33,10 @@ type mapper = {
class_type_field: mapper -> class_type_field -> class_type_field;
constructor_declaration: mapper -> constructor_declaration
-> constructor_declaration;
- exception_rebind: mapper -> exception_rebind -> exception_rebind;
expr: mapper -> expression -> expression;
extension: mapper -> extension -> extension;
+ extension_constructor: mapper -> extension_constructor
+ -> extension_constructor;
include_declaration: mapper -> include_declaration -> include_declaration;
include_description: mapper -> include_description -> include_description;
label_declaration: mapper -> label_declaration -> label_declaration;
@@ -55,6 +56,7 @@ type mapper = {
structure_item: mapper -> structure_item -> structure_item;
typ: mapper -> core_type -> core_type;
type_declaration: mapper -> type_declaration -> type_declaration;
+ type_extension: mapper -> type_extension -> type_extension;
type_kind: mapper -> type_kind -> type_kind;
value_binding: mapper -> value_binding -> value_binding;
value_description: mapper -> value_description -> value_description;
@@ -70,6 +72,16 @@ val default_mapper: mapper
(** {2 Apply mappers to compilation units} *)
+val tool_name: unit -> string
+(** Can be used within a ppx preprocessor to know which tool is
+ calling it ["ocamlc"], ["ocamlopt"], ["ocamldoc"], ["ocamldep"],
+ ["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],
+ [Clflags.debug]. *)
+
+
val apply: source:string -> target:string -> mapper -> unit
(** Apply a mapper (parametrized by the unit name) to a dumped
parsetree found in the [source] file and put the result in the
@@ -109,3 +121,21 @@ val register: string -> (string list -> mapper) -> unit
(** {2 Convenience functions to write mappers} *)
val map_opt: ('a -> 'b) -> 'a option -> 'b option
+
+val extension_of_error: Location.error -> extension
+(** Encode an error into an 'ocaml.error' extension node which can be
+ inserted in a generated Parsetree. The compiler will be
+ responsible for reporting the error. *)
+
+val attribute_of_warning: Location.t -> string -> attribute
+(** Encode a warning message into an 'ocaml.ppwarning' attribute which can be
+ inserted in a generated Parsetree. The compiler will be
+ responsible for reporting the warning. *)
+
+(** {2 Helper functions to call external mappers} *)
+
+val ppx_context: tool_name:string -> unit -> Parsetree.attribute
+(** Extract information from the current environment and encode it
+ into an attribute an attribute which can be prepended to
+ signature/structure items of an AST to pass the information to an
+ external processor. *)
diff --git a/parsing/lexer.mll b/parsing/lexer.mll
index 955e5dec25..237b44764c 100644
--- a/parsing/lexer.mll
+++ b/parsing/lexer.mll
@@ -94,7 +94,7 @@ let keyword_table =
(* To buffer string literals *)
-let initial_string_buffer = String.create 256
+let initial_string_buffer = Bytes.create 256
let string_buff = ref initial_string_buffer
let string_index = ref 0
@@ -103,12 +103,12 @@ let reset_string_buffer () =
string_index := 0
let store_string_char c =
- if !string_index >= String.length (!string_buff) then begin
- let new_buff = String.create (String.length (!string_buff) * 2) in
- String.blit (!string_buff) 0 new_buff 0 (String.length (!string_buff));
- string_buff := new_buff
+ 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;
- String.unsafe_set (!string_buff) (!string_index) c;
+ Bytes.unsafe_set !string_buff !string_index c;
incr string_index
let store_string s =
@@ -120,7 +120,7 @@ let store_lexeme lexbuf =
store_string (Lexing.lexeme lexbuf)
let get_stored_string () =
- let s = String.sub (!string_buff) 0 (!string_index) in
+ let s = Bytes.sub_string !string_buff 0 !string_index in
string_buff := initial_string_buffer;
s
@@ -181,13 +181,14 @@ let cvt_nativeint_literal s =
let remove_underscores s =
let l = String.length s in
+ let b = Bytes.create l in
let rec remove src dst =
if src >= l then
- if dst >= l then s else String.sub s 0 dst
+ if dst >= l then s else Bytes.sub_string b 0 dst
else
match s.[src] with
'_' -> remove (src + 1) dst
- | c -> s.[dst] <- c; remove (src + 1) (dst + 1)
+ | c -> Bytes.set b dst c; remove (src + 1) (dst + 1)
in remove 0 0
(* recover the name from a LABEL or OPTLABEL token *)
@@ -463,6 +464,7 @@ rule token = parse
| "!=" { INFIXOP0 "!=" }
| "+" { PLUS }
| "+." { PLUSDOT }
+ | "+=" { PLUSEQ }
| "-" { MINUS }
| "-." { MINUSDOT }
diff --git a/parsing/location.ml b/parsing/location.ml
index 669f2a2433..c6d1704f15 100644
--- a/parsing/location.ml
+++ b/parsing/location.ml
@@ -83,7 +83,7 @@ let highlight_terminfo ppf num_lines lb locs =
(* Count number of lines in phrase *)
let lines = ref !num_loc_lines in
for i = pos0 to lb.lex_buffer_len - 1 do
- if lb.lex_buffer.[i] = '\n' then incr lines
+ if Bytes.get lb.lex_buffer i = '\n' then incr lines
done;
(* If too many lines, give up *)
if !lines >= num_lines - 2 then raise Exit;
@@ -98,7 +98,7 @@ let highlight_terminfo ppf num_lines lb locs =
Terminfo.standout true;
if List.exists (fun loc -> pos = loc.loc_end.pos_cnum) locs then
Terminfo.standout false;
- let c = lb.lex_buffer.[pos + pos0] in
+ let c = Bytes.get lb.lex_buffer (pos + pos0) in
print_char c;
bol := (c = '\n')
done;
@@ -119,7 +119,7 @@ let highlight_dumb ppf lb loc =
(* 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 lb.lex_buffer.[pos + pos0] = '\n' then begin
+ 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
@@ -132,7 +132,7 @@ let highlight_dumb ppf lb loc =
let line = ref 0 in
let pos_at_bol = ref 0 in
for pos = 0 to end_pos do
- match lb.lex_buffer.[pos + pos0] with
+ 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 *)
@@ -367,3 +367,16 @@ let report_exception ppf exn =
match error_of_exn exn with
| Some err -> fprintf ppf "@[%a@]@." report_error err
| None -> raise exn
+
+
+exception Error of error
+
+let () =
+ register_error_of_exn
+ (function
+ | Error e -> Some e
+ | _ -> None
+ )
+
+let raise_errorf ?(loc = none) ?(sub = []) ?(if_highlight = "") =
+ Printf.ksprintf (fun msg -> raise (Error ({loc; msg; sub; if_highlight})))
diff --git a/parsing/location.mli b/parsing/location.mli
index 8287d1ec9a..1a7feeb4da 100644
--- a/parsing/location.mli
+++ b/parsing/location.mli
@@ -89,11 +89,16 @@ type error =
if_highlight: string; (* alternative message if locations are highlighted *)
}
+exception Error of error
+
val error: ?loc:t -> ?sub:error list -> ?if_highlight:string -> string -> error
val errorf: ?loc:t -> ?sub:error list -> ?if_highlight:string
-> ('a, unit, string, error) format4 -> 'a
+val raise_errorf: ?loc:t -> ?sub:error list -> ?if_highlight:string
+ -> ('a, unit, string, 'b) format4 -> 'a
+
val error_of_printer: t -> (formatter -> 'a -> unit) -> 'a -> error
val error_of_printer_file: (formatter -> 'a -> unit) -> 'a -> error
diff --git a/parsing/parser.mly b/parsing/parser.mly
index 172ad940ca..fa0d3c636a 100644
--- a/parsing/parser.mly
+++ b/parsing/parser.mly
@@ -237,7 +237,8 @@ let varify_constructors var_names t =
| Ptyp_constr(longident, lst) ->
Ptyp_constr(longident, List.map loop lst)
| Ptyp_object (lst, o) ->
- Ptyp_object (List.map (fun (s, t) -> (s, loop t)) lst, o)
+ Ptyp_object
+ (List.map (fun (s, attrs, t) -> (s, attrs, loop t)) lst, o)
| Ptyp_class (longident, lst) ->
Ptyp_class (longident, List.map loop lst)
| Ptyp_alias(core_type, string) ->
@@ -257,8 +258,8 @@ let varify_constructors var_names t =
{t with ptyp_desc = desc}
and loop_row_field =
function
- | Rtag(label,flag,lst) ->
- Rtag(label,flag,List.map loop lst)
+ | Rtag(label,attrs,flag,lst) ->
+ Rtag(label,attrs,flag,List.map loop lst)
| Rinherit t ->
Rinherit (loop t)
in
@@ -282,6 +283,12 @@ let wrap_exp_attrs body (ext, attrs) =
let mkexp_attrs d attrs =
wrap_exp_attrs (mkexp d) attrs
+let mkcf_attrs d attrs =
+ Cf.mk ~loc:(symbol_rloc()) ~attrs d
+
+let mkctf_attrs d attrs =
+ Ctf.mk ~loc:(symbol_rloc()) ~attrs d
+
%}
/* Tokens */
@@ -374,6 +381,7 @@ let mkexp_attrs d attrs =
%token PERCENT
%token PLUS
%token PLUSDOT
+%token PLUSEQ
%token <string> PREFIXOP
%token PRIVATE
%token QUESTION
@@ -453,10 +461,8 @@ The precedences must be listed from low to high.
%nonassoc below_LBRACKETAT
%nonassoc LBRACKETAT
%nonassoc LBRACKETATAT
-%nonassoc LBRACKETPERCENT
-%nonassoc LBRACKETPERCENTPERCENT
%right COLONCOLON /* expr (e :: e :: e) */
-%left INFIXOP2 PLUS PLUSDOT MINUS MINUSDOT /* expr (e OP e OP e) */
+%left INFIXOP2 PLUS PLUSDOT MINUS MINUSDOT PLUSEQ /* expr (e OP e OP e) */
%left PERCENT INFIXOP3 STAR /* expr (e OP e OP e) */
%right INFIXOP4 /* expr (e OP e OP e) */
%nonassoc prec_unary_minus prec_unary_plus /* unary - */
@@ -470,6 +476,7 @@ The precedences must be listed from low to high.
%nonassoc BACKQUOTE BANG BEGIN CHAR FALSE FLOAT INT INT32 INT64
LBRACE LBRACELESS LBRACKET LBRACKETBAR LIDENT LPAREN
NEW NATIVEINT PREFIXOP STRING TRUE UIDENT
+ LBRACKETPERCENT LBRACKETPERCENTPERCENT
/* Entry points */
@@ -522,9 +529,9 @@ use_file_tail:
| SEMISEMI seq_expr post_item_attributes use_file_tail
{ Ptop_def[mkstrexp $2 $3] :: $4 }
| SEMISEMI structure_item use_file_tail { Ptop_def[$2] :: $3 }
- | SEMISEMI toplevel_directive SEMISEMI use_file_tail { $2 :: $4 }
+ | SEMISEMI toplevel_directive use_file_tail { $2 :: $3 }
| structure_item use_file_tail { Ptop_def[$1] :: $2 }
- | toplevel_directive SEMISEMI use_file_tail { $1 :: $3 }
+ | toplevel_directive use_file_tail { $1 :: $2 }
;
parse_core_type:
core_type EOF { $1 }
@@ -637,12 +644,10 @@ structure_item:
~prim:$6 ~attrs:$7 ~loc:(symbol_rloc ()))) }
| TYPE type_declarations
{ mkstr(Pstr_type (List.rev $2) ) }
- | EXCEPTION exception_declaration
+ | TYPE str_type_extension
+ { mkstr(Pstr_typext $2) }
+ | EXCEPTION str_exception_declaration
{ mkstr(Pstr_exception $2) }
- | EXCEPTION UIDENT EQUAL constr_longident post_item_attributes
- { mkstr (Pstr_exn_rebind
- (Exrb.mk (mkrhs $2 2)
- (mkloc $4 (rhs_loc 4)) ~attrs:$5 ~loc:(symbol_rloc()))) }
| MODULE module_binding
{ mkstr(Pstr_module $2) }
| MODULE REC module_bindings
@@ -726,7 +731,9 @@ signature_item:
~loc:(symbol_rloc()))) }
| TYPE type_declarations
{ mksig(Psig_type (List.rev $2)) }
- | EXCEPTION exception_declaration
+ | TYPE sig_type_extension
+ { mksig(Psig_typext $2) }
+ | EXCEPTION sig_exception_declaration
{ mksig(Psig_exception $2) }
| MODULE UIDENT module_declaration post_item_attributes
{ mksig(Psig_module (Md.mk (mkrhs $2 2)
@@ -864,19 +871,20 @@ class_fields:
{ $2 :: $1 }
;
class_field:
- | INHERIT override_flag class_expr parent_binder
- { mkcf (Pcf_inherit ($2, $3, $4)) }
- | VAL value
- { mkcf (Pcf_val $2) }
- | METHOD method_
- { mkcf (Pcf_method $2) }
- | CONSTRAINT constrain_field
- { mkcf (Pcf_constraint $2) }
- | INITIALIZER seq_expr
- { mkcf (Pcf_initializer $2) }
- | class_field post_item_attribute
- { Cf.attr $1 $2 }
- | item_extension { mkcf(Pcf_extension $1) }
+ | INHERIT override_flag class_expr parent_binder post_item_attributes
+ { mkcf_attrs (Pcf_inherit ($2, $3, $4)) $5 }
+ | VAL value post_item_attributes
+ { mkcf_attrs (Pcf_val $2) $3 }
+ | METHOD method_ post_item_attributes
+ { mkcf_attrs (Pcf_method $2) $3 }
+ | CONSTRAINT constrain_field post_item_attributes
+ { mkcf_attrs (Pcf_constraint $2) $3 }
+ | INITIALIZER seq_expr post_item_attributes
+ { mkcf_attrs (Pcf_initializer $2) $3 }
+ | item_extension post_item_attributes
+ { mkcf_attrs (Pcf_extension $1) $2 }
+ | floating_attribute
+ { mkcf (Pcf_attribute $1) }
;
parent_binder:
AS LIDENT
@@ -964,16 +972,21 @@ class_sig_fields:
| class_sig_fields class_sig_field { $2 :: $1 }
;
class_sig_field:
- INHERIT class_signature { mkctf (Pctf_inherit $2) }
- | VAL value_type { mkctf (Pctf_val $2) }
- | METHOD private_virtual_flags label COLON poly_type
+ INHERIT class_signature post_item_attributes
+ { mkctf_attrs (Pctf_inherit $2) $3 }
+ | VAL value_type post_item_attributes
+ { mkctf_attrs (Pctf_val $2) $3 }
+ | METHOD private_virtual_flags label COLON poly_type post_item_attributes
{
let (p, v) = $2 in
- mkctf (Pctf_method ($3, p, v, $5))
+ mkctf_attrs (Pctf_method ($3, p, v, $5)) $6
}
- | CONSTRAINT constrain_field { mkctf (Pctf_constraint $2) }
- | class_sig_field post_item_attribute { Ctf.attr $1 $2 }
- | item_extension { mkctf(Pctf_extension $1) }
+ | CONSTRAINT constrain_field post_item_attributes
+ { mkctf_attrs (Pctf_constraint $2) $3 }
+ | item_extension post_item_attributes
+ { mkctf_attrs (Pctf_extension $1) $2 }
+ | floating_attribute
+ { mkctf(Pctf_attribute $1) }
;
value_type:
VIRTUAL mutable_flag label COLON core_type
@@ -1121,6 +1134,8 @@ 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
@@ -1432,6 +1447,8 @@ pattern:
{ expecting 3 "pattern" }
| LAZY simple_pattern
{ mkpat(Ppat_lazy $2) }
+ | EXCEPTION pattern %prec prec_constr_appl
+ { mkpat(Ppat_exception $2) }
| pattern attribute
{ Pat.attr $1 $2 }
;
@@ -1550,27 +1567,33 @@ type_kind:
{ (Ptype_variant(List.rev $3), Private, None) }
| EQUAL private_flag BAR constructor_declarations
{ (Ptype_variant(List.rev $4), $2, None) }
+ | EQUAL DOTDOT
+ { (Ptype_open, Public, None) }
| EQUAL private_flag LBRACE label_declarations opt_semi RBRACE
{ (Ptype_record(List.rev $4), $2, None) }
| EQUAL core_type EQUAL private_flag opt_bar constructor_declarations
{ (Ptype_variant(List.rev $6), $4, Some $2) }
+ | EQUAL core_type EQUAL DOTDOT
+ { (Ptype_open, Public, Some $2) }
| EQUAL core_type EQUAL private_flag LBRACE label_declarations opt_semi RBRACE
{ (Ptype_record(List.rev $6), $4, Some $2) }
;
optional_type_parameters:
/*empty*/ { [] }
- | optional_type_parameter { [$1] }
+ | optional_type_parameter { [$1] }
| LPAREN optional_type_parameter_list RPAREN { List.rev $2 }
;
optional_type_parameter:
- type_variance QUOTE ident { Some (mkrhs $3 3), $1 }
- | type_variance UNDERSCORE { None, $1 }
+ 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) }
+;
type_parameters:
@@ -1579,13 +1602,16 @@ type_parameters:
| LPAREN type_parameter_list RPAREN { List.rev $2 }
;
type_parameter:
- type_variance QUOTE ident { mkrhs $3 3, $1 }
+ type_variance type_variable { $2, $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 }
@@ -1601,11 +1627,23 @@ constructor_declaration:
Type.constructor (mkrhs $1 1) ~args ?res ~loc:(symbol_rloc()) ~attrs:$2
}
;
-exception_declaration:
- | constructor_declaration post_item_attributes
+str_exception_declaration:
+ | extension_constructor_declaration post_item_attributes
+ {
+ let ext = $1 in
+ {ext with pext_attributes = ext.pext_attributes @ $2}
+ }
+ | extension_constructor_rebind post_item_attributes
+ {
+ let ext = $1 in
+ {ext with pext_attributes = ext.pext_attributes @ $2}
+ }
+;
+sig_exception_declaration:
+ | extension_constructor_declaration post_item_attributes
{
- let cd = $1 in
- {cd with pcd_attributes = cd.pcd_attributes @ $2}
+ let ext = $1 in
+ {ext with pext_attributes = ext.pext_attributes @ $2}
}
;
generalized_constructor_arguments:
@@ -1632,6 +1670,43 @@ label_declaration:
}
;
+/* Type Extensions */
+
+str_type_extension:
+ optional_type_parameters type_longident
+ PLUSEQ private_flag opt_bar str_extension_constructors post_item_attributes
+ { Te.mk (mkrhs $2 2) (List.rev $6)
+ ~params:$1 ~priv:$4 ~attrs:$7 }
+;
+sig_type_extension:
+ optional_type_parameters type_longident
+ PLUSEQ private_flag opt_bar sig_extension_constructors post_item_attributes
+ { Te.mk (mkrhs $2 2) (List.rev $6)
+ ~params:$1 ~priv:$4 ~attrs:$7 }
+;
+str_extension_constructors:
+ extension_constructor_declaration { [$1] }
+ | extension_constructor_rebind { [$1] }
+ | str_extension_constructors BAR extension_constructor_declaration
+ { $3 :: $1 }
+ | str_extension_constructors BAR extension_constructor_rebind
+ { $3 :: $1 }
+;
+sig_extension_constructors:
+ extension_constructor_declaration { [$1] }
+ | sig_extension_constructors BAR extension_constructor_declaration
+ { $3 :: $1 }
+;
+extension_constructor_declaration:
+ | constr_ident attributes generalized_constructor_arguments
+ { let args, res = $3 in
+ Te.decl (mkrhs $1 1) ~args ?res ~loc:(symbol_rloc()) ~attrs:$2 }
+;
+extension_constructor_rebind:
+ | constr_ident attributes EQUAL constr_longident
+ { Te.rebind (mkrhs $1 1) (mkrhs $4 4) ~loc:(symbol_rloc()) ~attrs:$2 }
+;
+
/* "with" constraints (additional type equations over signature components) */
with_constraints:
@@ -1643,7 +1718,7 @@ with_constraint:
{ Pwith_type
(mkrhs $3 3,
(Type.mk (mkrhs (Longident.last $3) 3)
- ~params:(List.map (fun (x, v) -> Some x, v) $2)
+ ~params:$2
~cstrs:(List.rev $6)
~manifest:$5
~priv:$4
@@ -1653,7 +1728,7 @@ with_constraint:
| TYPE type_parameters label COLONEQUAL core_type
{ Pwith_typesubst
(Type.mk (mkrhs $3 3)
- ~params:(List.map (fun (x, v) -> Some x, v) $2)
+ ~params:$2
~manifest:$5
~loc:(symbol_rloc())) }
| MODULE mod_longident EQUAL mod_ext_longident
@@ -1780,10 +1855,10 @@ row_field:
| simple_core_type { Rinherit $1 }
;
tag_field:
- name_tag OF opt_ampersand amper_type_list
- { Rtag ($1, $3, List.rev $4) }
- | name_tag
- { Rtag ($1, true, []) }
+ name_tag attributes OF opt_ampersand amper_type_list
+ { Rtag ($1, $2, $4, List.rev $5) }
+ | name_tag attributes
+ { Rtag ($1, $2, true, []) }
;
opt_ampersand:
AMPERSAND { true }
@@ -1826,7 +1901,7 @@ meth_list:
| DOTDOT { [], Open }
;
field:
- label COLON poly_type /* ok */ { ($1, $3) }
+ label attributes COLON poly_type { ($1, $2, $4) }
;
label:
LIDENT { $1 }
@@ -1891,6 +1966,7 @@ operator:
| AMPERSAND { "&" }
| AMPERAMPER { "&&" }
| COLONEQUAL { ":=" }
+ | PLUSEQ { "+=" }
| PERCENT { "%" }
;
constr_ident:
@@ -1951,23 +2027,15 @@ class_longident:
/* Toplevel directives */
toplevel_directive:
- SHARP ident toplevel_directive_args { Ptop_dir($2, $3) }
-;
-toplevel_directive_arg:
- | STRING { Pdir_string (fst $1) }
- | INT { Pdir_int $1 }
- | val_longident { Pdir_ident $1 }
- | mod_longident { Pdir_ident $1 }
- | keyword {
- match $1 with
- | "true" -> Pdir_bool true
- | "false" -> Pdir_bool false
- | s -> Pdir_keyword s
- }
-toplevel_directive_args:
- | /*empty*/ { [] }
- | toplevel_directive_arg toplevel_directive_args { $1 :: $2 }
+ SHARP ident { Ptop_dir($2, Pdir_none) }
+ | SHARP ident STRING { Ptop_dir($2, Pdir_string (fst $3)) }
+ | SHARP ident INT { Ptop_dir($2, Pdir_int $3) }
+ | SHARP ident val_longident { Ptop_dir($2, Pdir_ident $3) }
+ | SHARP ident mod_longident { Ptop_dir($2, Pdir_ident $3) }
+ | SHARP ident FALSE { Ptop_dir($2, Pdir_bool false) }
+ | SHARP ident TRUE { Ptop_dir($2, Pdir_bool true) }
;
+
/* Miscellaneous */
name_tag:
@@ -2023,7 +2091,9 @@ additive:
/* Attributes and extensions */
-keyword:
+single_attr_id:
+ LIDENT { $1 }
+ | UIDENT { $1 }
| AND { "and" }
| AS { "as" }
| ASSERT { "assert" }
@@ -2074,11 +2144,6 @@ keyword:
| WITH { "with" }
/* mod/land/lor/lxor/lsl/lsr/asr are not supported for now */
;
-single_attr_id:
- LIDENT { $1 }
- | UIDENT { $1 }
- | keyword { $1 }
-;
attr_id:
single_attr_id { mkloc $1 (symbol_rloc()) }
diff --git a/parsing/parsetree.mli b/parsing/parsetree.mli
index a984c7800d..75b8528c65 100644
--- a/parsing/parsetree.mli
+++ b/parsing/parsetree.mli
@@ -66,7 +66,7 @@ and core_type_desc =
T tconstr
(T1, ..., Tn) tconstr
*)
- | Ptyp_object of (string * core_type) list * closed_flag
+ | Ptyp_object of (string * attributes * core_type) list * closed_flag
(* < l1:T1; ...; ln:Tn > (flag = Closed)
< l1:T1; ...; ln:Tn; .. > (flag = Open)
*)
@@ -115,7 +115,7 @@ and package_type = Longident.t loc * (Longident.t loc * core_type) list
*)
and row_field =
- | Rtag of label * bool * core_type list
+ | Rtag of label * attributes * bool * core_type list
(* [`A] ( true, [] )
[`A of T] ( false, [T] )
[`A of T1 & .. & Tn] ( false, [T1;...Tn] )
@@ -125,6 +125,8 @@ and row_field =
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 ] *)
@@ -182,6 +184,8 @@ and pattern_desc =
Note: (module P : S) is represented as
Ppat_constraint(Ppat_unpack, Ptyp_package)
*)
+ | Ppat_exception of pattern
+ (* exception P *)
| Ppat_extension of extension
(* [%id] *)
@@ -332,7 +336,7 @@ and value_description =
and type_declaration =
{
ptype_name: string loc;
- ptype_params: (string loc option * variance) list;
+ ptype_params: (core_type * variance) list;
(* ('a1,...'an) t; None represents _*)
ptype_cstrs: (core_type * core_type * Location.t) list;
(* ... constraint T1=T1' ... constraint Tn=Tn' *)
@@ -350,12 +354,14 @@ and type_declaration =
type t = T0 = C of T | ... (variant, manifest=T0)
type t = {l: T; ...} (record, no manifest)
type t = T0 = {l : T; ...} (record, manifest=T0)
+ type t = .. (open, no manifest)
*)
and type_kind =
| Ptype_abstract
| Ptype_variant of constructor_declaration list
| Ptype_record of label_declaration list
+ | Ptype_open
and label_declaration =
{
@@ -394,14 +400,37 @@ and constructor_arguments =
| C of {...} as t (res = None, args = Pcstr_record)
*)
-and exception_rebind =
+and type_extension =
{
- pexrb_name: string loc;
- pexrb_lid: Longident.t loc;
- pexrb_loc: Location.t;
- pexrb_attributes: attributes;
+ ptyext_path: Longident.t loc;
+ ptyext_params: (core_type * variance) list;
+ ptyext_constructors: extension_constructor list;
+ ptyext_private: private_flag;
+ ptyext_attributes: attributes; (* ... [@@id1] [@@id2] *)
}
-(* exception C = M.X *)
+(*
+ type t += ...
+*)
+
+and extension_constructor =
+ {
+ pext_name: string loc;
+ pext_kind : extension_constructor_kind;
+ pext_loc : Location.t;
+ pext_attributes: attributes; (* C [@id1] [@id2] of ... *)
+ }
+
+and extension_constructor_kind =
+ Pext_decl of constructor_arguments * core_type option
+ (*
+ | C of T1 * ... * Tn ([T1; ...; Tn], None)
+ | C: T0 ([], Some T0)
+ | C: T1 * ... * Tn -> T0 ([T1; ...; Tn], Some T0)
+ *)
+ | Pext_rebind of Longident.t loc
+ (*
+ | C = D
+ *)
(** {2 Class language} *)
@@ -456,13 +485,15 @@ and class_type_field_desc =
*)
| Pctf_constraint of (core_type * core_type)
(* constraint T1 = T2 *)
+ | Pctf_attribute of attribute
+ (* [@@@id] *)
| Pctf_extension of extension
(* [%%id] *)
and 'a class_infos =
{
pci_virt: virtual_flag;
- pci_params: (string loc * variance) list;
+ pci_params: (core_type * variance) list;
pci_name: string loc;
pci_expr: 'a;
pci_loc: Location.t;
@@ -549,6 +580,8 @@ and class_field_desc =
(* constraint T1 = T2 *)
| Pcf_initializer of expression
(* initializer E *)
+ | Pcf_attribute of attribute
+ (* [@@@id] *)
| Pcf_extension of extension
(* [%%id] *)
@@ -601,7 +634,9 @@ and signature_item_desc =
*)
| Psig_type of type_declaration list
(* type t1 = ... and ... and tn = ... *)
- | Psig_exception of constructor_declaration
+ | Psig_typext of type_extension
+ (* type t1 += ... *)
+ | Psig_exception of extension_constructor
(* exception C of T *)
| Psig_module of module_declaration
(* module X : MT *)
@@ -725,10 +760,11 @@ and structure_item_desc =
(* external x: T = "s1" ... "sn" *)
| Pstr_type of type_declaration list
(* type t1 = ... and ... and tn = ... *)
- | Pstr_exception of constructor_declaration
- (* exception C of T *)
- | Pstr_exn_rebind of exception_rebind
- (* exception C = M.X *)
+ | Pstr_typext of type_extension
+ (* type t1 += ... *)
+ | Pstr_exception of extension_constructor
+ (* exception C of T
+ exception C = M.X *)
| Pstr_module of module_binding
(* module X = ME *)
| Pstr_recmodule of module_binding list
@@ -771,12 +807,12 @@ and module_binding =
type toplevel_phrase =
| Ptop_def of structure
- | Ptop_dir of string * directive_argument list
+ | Ptop_dir of string * directive_argument
(* #use, #load ... *)
and directive_argument =
+ | Pdir_none
| Pdir_string of string
| Pdir_int of int
| Pdir_ident of Longident.t
| Pdir_bool of bool
- | Pdir_keyword of string
diff --git a/parsing/pprintast.ml b/parsing/pprintast.ml
index 7e2a6428d7..3fb3494b3d 100644
--- a/parsing/pprintast.ml
+++ b/parsing/pprintast.ml
@@ -76,8 +76,8 @@ let protect_ident ppf txt =
let protect_longident ppf print_longident longprefix txt =
let format : (_, _, _) format =
if not (needs_parens txt) then "%a.%s"
- else if needs_spaces txt then "(@;%a.%s@;)"
- else "(%a.%s)" in
+ else if needs_spaces txt then "%a.(@;%s@;)"
+ else "%a.(%s)" in
fprintf ppf format print_longident longprefix txt
type space_formatter = (unit, Format.formatter, unit) format
@@ -126,19 +126,6 @@ let is_simple_construct :construct -> bool = function
let pp = fprintf
-let rec is_irrefut_patt x =
- match x.ppat_desc with
- | Ppat_any | Ppat_var _ | Ppat_unpack _ -> true
- | Ppat_alias (p,_) -> is_irrefut_patt p
- | Ppat_tuple (ps) -> List.for_all is_irrefut_patt ps
- | Ppat_constraint (p,_) -> is_irrefut_patt p
- | Ppat_or (l,r) -> is_irrefut_patt l || is_irrefut_patt r
- | Ppat_record (ls,_) -> List.for_all (fun (_,x) -> is_irrefut_patt x) ls
- | Ppat_lazy p -> is_irrefut_patt p
- | Ppat_extension _ -> assert false
- | Ppat_interval _
- | Ppat_constant _ | Ppat_construct _ | Ppat_variant _ | Ppat_array _
- | Ppat_type _-> false (*conservative*)
class printer ()= object(self:'self)
val pipe = false
val semi = false
@@ -163,9 +150,9 @@ class printer ()= object(self:'self)
| xs ->
let rec loop f = function
| [x] -> fu f x
- | x::xs -> pp f "%a%(%)%a" fu x sep loop xs
+ | x::xs -> fu f x; pp f sep; loop f xs;
| _ -> assert false in begin
- pp f "%(%)%a%(%)" first loop xs last;
+ pp f first; loop f xs; pp f last;
end in
aux f xs
method option : 'a. ?first:space_formatter -> ?last:space_formatter ->
@@ -175,11 +162,11 @@ class printer ()= object(self:'self)
and last = match last with Some x -> x | None -> "" in
match a with
| None -> ()
- | Some x -> pp f "%(%)%a%(%)" first fu x last
+ | Some x -> pp f first; fu f x; pp f last;
method paren: 'a . ?first:space_formatter -> ?last:space_formatter ->
bool -> (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a -> unit =
fun ?(first="") ?(last="") b fu f x ->
- if b then pp f "(%(%)%a%(%))" first fu x last
+ if b then (pp f "("; pp f first; fu f x; pp f last; pp f ")")
else fu f x
@@ -223,18 +210,13 @@ class printer ()= object(self:'self)
method constant_string f s = pp f "%S" s
method tyvar f str = pp f "'%s" str
method string_quot f x = pp f "`%s" x
- method type_var_option f str =
- match str with
- | None -> pp f "_" (* wildcard*)
- | Some {txt;_} -> self#tyvar f txt
(* c ['a,'b] *)
method class_params_def f = function
| [] -> ()
| l ->
pp f "[%a] " (* space *)
- (self#list (fun f ({txt;_},s) ->
- pp f "%s%a" (type_variance s) self#tyvar txt) ~sep:",") l
+ (self#list self#type_param ~sep:",") l
method type_with_label f (label,({ptyp_desc;_}as c) ) =
match label with
@@ -286,7 +268,7 @@ class printer ()= object(self:'self)
| Ptyp_variant (l, closed, low) ->
let type_variant_helper f x =
match x with
- | Rtag (l, _, ctl) -> pp f "@[<2>%a%a@]" self#string_quot l
+ | Rtag (l, _attrs, _, ctl) -> pp f "@[<2>%a%a@]" self#string_quot l
(fun f l -> match l with
|[] -> ()
| _ -> pp f "@;of@;%a"
@@ -312,7 +294,7 @@ class printer ()= object(self:'self)
pp f ">@ %a"
(self#list self#string_quot) xs) low
| Ptyp_object (l, o) ->
- let core_field_type f (s, ct) =
+ let core_field_type f (s, _attrs, ct) =
pp f "@[<hov2>%s@ :%a@ @]" s self#core_type ct
in
let field_var f = function
@@ -412,6 +394,8 @@ class printer ()= object(self:'self)
pp f "@[<2>(%a@;:@;%a)@]" self#pattern1 p self#core_type ct
| Ppat_lazy p ->
pp f "@[<2>(lazy@;%a)@]" self#pattern1 p
+ | Ppat_exception p ->
+ pp f "@[<2>exception@;%a@]" self#pattern1 p
| _ -> self#paren true self#pattern f x
method label_exp f (l,opt,p) =
@@ -708,13 +692,8 @@ class printer ()= object(self:'self)
end) x
- method exception_declaration f cd =
- pp f "@[<hov2>exception@ %s%a@]" cd.pcd_name.txt
- (fun f ed -> match ed with
- | Pcstr_tuple [] -> ()
- | Pcstr_tuple l -> pp f "@ of@ %a" (self#list ~sep:"*" self#core_type) l
- | Pcstr_record _ -> assert false (* TODO *)
- ) cd.pcd_args
+ method exception_declaration f ext =
+ pp f "@[<hov2>exception@ %a@]" self#extension_constructor ext
method class_signature f { pcsig_self = ct; pcsig_fields = l ;_} =
let class_type_field f x =
@@ -730,6 +709,7 @@ class printer ()= object(self:'self)
| Pctf_constraint (ct1, ct2) ->
pp f "@[<2>constraint@ %a@ =@ %a@]"
self#core_type ct1 self#core_type ct2
+ | Pctf_attribute _ -> ()
| Pctf_extension _ -> assert false
in
pp f "@[<hv0>@[<hv2>object @[<1>%a@]@ %a@]@ end@]"
@@ -804,6 +784,7 @@ class printer ()= object(self:'self)
pp f "@[<2>constraint %a =@;%a@]" self#core_type ct1 self#core_type ct2
| Pcf_initializer (e) ->
pp f "@[<2>initializer@ %a@]" self#expression e
+ | Pcf_attribute _ -> ()
| Pcf_extension _ -> assert false
method class_structure f { pcstr_self = p; pcstr_fields = l } =
@@ -858,14 +839,14 @@ class printer ()= object(self:'self)
| Pwith_type (li, ({ptype_params= ls ;_} as td)) ->
let ls = List.map fst ls in
pp f "type@ %a %a =@ %a"
- (self#list self#type_var_option ~sep:"," ~first:"(" ~last:")")
+ (self#list self#core_type ~sep:"," ~first:"(" ~last:")")
ls self#longident_loc li self#type_declaration td
| Pwith_module (li, li2) ->
pp f "module %a =@ %a" self#longident_loc li self#longident_loc li2;
| Pwith_typesubst ({ptype_params=ls;_} as td) ->
let ls = List.map fst ls in
pp f "type@ %a %s :=@ %a"
- (self#list self#type_var_option ~sep:"," ~first:"(" ~last:")")
+ (self#list self#core_type ~sep:"," ~first:"(" ~last:")")
ls td.ptype_name.txt
self#type_declaration td
| Pwith_modsubst (s, li2) ->
@@ -891,6 +872,8 @@ class printer ()= object(self:'self)
let intro = if vd.pval_prim = [] then "val" else "external" in
pp f "%s@ %a@ :@ " intro protect_ident vd.pval_name.txt;
self#value_description f vd;) vd
+ | Psig_typext te ->
+ self#type_extension f te
| Psig_exception ed ->
self#exception_declaration f ed
| Psig_class l ->
@@ -1043,6 +1026,7 @@ class printer ()= object(self:'self)
| Pstr_type l -> self#type_def_list f l
| Pstr_value (rf, l) -> (* pp f "@[<hov2>let %a%a@]" self#rec_flag rf self#bindings l *)
pp f "@[<2>%a@]" self#bindings (rf,l)
+ | Pstr_typext te -> self#type_extension f te
| Pstr_exception ed -> self#exception_declaration f ed
| Pstr_module x ->
let rec module_helper me = match me.pmod_desc with
@@ -1117,10 +1101,6 @@ class printer ()= object(self:'self)
self#value_description vd
| Pstr_include incl ->
pp f "@[<hov2>include@ %a@]" self#module_expr incl.pincl_mod
- | Pstr_exn_rebind er -> (* todo: check this *)
- pp f "@[<hov2>exception@ %s@ =@ %a@]"
- er.pexrb_name.txt
- self#longident_loc er.pexrb_lid
| Pstr_recmodule decls -> (* 3.07 *)
let aux f = function
| {pmb_name = s; pmb_expr={pmod_desc=Pmod_constraint (expr, typ)}} ->
@@ -1140,8 +1120,8 @@ class printer ()= object(self:'self)
| Pstr_attribute _ -> ()
| Pstr_extension _ -> assert false
end
- method type_param f (opt, a) =
- pp f "%s%a" (type_variance a ) self#type_var_option opt
+ method type_param f (ct, a) =
+ pp f "%s%a" (type_variance a) self#core_type ct
(* shared by [Pstr_type,Psig_type]*)
method type_def_list f l =
let aux f ({ptype_name = s; ptype_params;ptype_kind;ptype_manifest;_} as td) =
@@ -1201,6 +1181,8 @@ class printer ()= object(self:'self)
pp f "@[<2>%a%s:@;%a@]" self#mutable_flag pld.pld_mutable pld.pld_name.txt self#core_type pld.pld_type in
pp f "{@\n%a}"
(self#list type_record_field ~sep:";@\n" ) l ;
+ | Ptype_open ->
+ pp f ".."
) x
(self#list
(fun f (ct1,ct2,_) ->
@@ -1208,6 +1190,46 @@ class printer ()= object(self:'self)
self#core_type ct1 self#core_type ct2 )) x.ptype_cstrs ;
(* TODO: attributes *)
end
+
+ method type_extension f x =
+ let extension_constructor f x =
+ pp f "@\n|@;%a" self#extension_constructor x
+ in
+ pp f "@[<2>type %a%a +=@;%a@]"
+ (fun f -> function
+ | [] -> ()
+ | l -> pp f "%a@;" (self#list self#type_param ~first:"(" ~last:")" ~sep:",") l)
+ x.ptyext_params
+ self#longident_loc x.ptyext_path
+ (self#list ~sep:"" extension_constructor)
+ x.ptyext_constructors
+
+ method extension_constructor f x =
+ match x.pext_kind with
+ | Pext_decl(l, None) ->
+ pp f "%s%a" x.pext_name.txt
+ (fun f -> function
+ | Pcstr_tuple [] -> ()
+ | Pcstr_tuple l ->
+ pp f "@;of@;%a" (self#list self#core_type1 ~sep:"*@;") l
+ | Pcstr_record _ ->
+ pp f "{...}" (* #5528: TODO *)
+ ) l
+ | Pext_decl(l, Some r) ->
+ pp f "%s:@;%a" x.pext_name.txt
+ (fun f -> function
+ | Pcstr_tuple [] -> self#core_type1 f r
+ | Pcstr_tuple l -> pp f "%a@;->@;%a"
+ (self#list self#core_type1 ~sep:"*@;") l
+ self#core_type1 r
+ | Pcstr_record _ ->
+ pp f "{...}" (* #5528: TODO *)
+ )
+ l
+ | Pext_rebind li ->
+ pp f "%s@ = @ %a" x.pext_name.txt
+ self#longident_loc li
+
method case_list f l : unit =
let aux f {pc_lhs; pc_guard; pc_rhs} =
pp f "@;| @[<2>%a%a@;->@;%a@]"
@@ -1233,12 +1255,12 @@ class printer ()= object(self:'self)
pp f "~%s:%a" lbl self#simple_expr e
method directive_argument f x =
- match x with
+ (match x with
+ | Pdir_none -> ()
| Pdir_string (s) -> pp f "@ %S" s
| Pdir_int (i) -> pp f "@ %d" i
| Pdir_ident (li) -> pp f "@ %a" self#longident li
- | Pdir_bool (b) -> pp f "@ %s" (string_of_bool b)
- | Pdir_keyword s -> pp f "@ %s" s
+ | Pdir_bool (b) -> pp f "@ %s" (string_of_bool b))
method toplevel_phrase f x =
match x with
@@ -1247,8 +1269,7 @@ class printer ()= object(self:'self)
self#list self#structure_item f s ;
pp_close_box f ();
| Ptop_dir (s, da) ->
- pp f "@[<hov2>#%s@ %a@]" s
- (self#list ~sep:" " self#directive_argument) da
+ pp f "@[<hov2>#%s@ %a@]" s self#directive_argument da
end;;
@@ -1262,8 +1283,7 @@ let toplevel_phrase f x =
(* pp_print_list structure_item f s ; *)
(* pp_close_box f (); *)
| Ptop_dir (s, da) ->
- pp f "@[<hov2>#%s@ %a@]" s
- (default#list ~sep:" " default#directive_argument) da
+ pp f "@[<hov2>#%s@ %a@]" s default#directive_argument da
(* pp f "@[<hov2>#%s@ %a@]" s directive_argument da *)
let expression f x =
diff --git a/parsing/pprintast.mli b/parsing/pprintast.mli
index 86297cea82..316218d310 100644
--- a/parsing/pprintast.mli
+++ b/parsing/pprintast.mli
@@ -27,7 +27,7 @@ class printer :
method class_expr : Format.formatter -> Parsetree.class_expr -> unit
method class_field : Format.formatter -> Parsetree.class_field -> unit
method class_params_def :
- Format.formatter -> (string Asttypes.loc * Asttypes.variance) list -> unit
+ Format.formatter -> (Parsetree.core_type * Asttypes.variance) list -> unit
method class_signature :
Format.formatter -> Parsetree.class_signature -> unit
method class_structure :
@@ -44,10 +44,12 @@ class printer :
method directive_argument :
Format.formatter -> Parsetree.directive_argument -> unit
method exception_declaration :
- Format.formatter -> Parsetree.constructor_declaration -> unit
+ Format.formatter -> Parsetree.extension_constructor -> unit
method expression : Format.formatter -> Parsetree.expression -> unit
method expression1 : Format.formatter -> Parsetree.expression -> unit
method expression2 : Format.formatter -> Parsetree.expression -> unit
+ method extension_constructor :
+ Format.formatter -> Parsetree.extension_constructor -> unit
method label_exp :
Format.formatter ->
Asttypes.label * Parsetree.expression option * Parsetree.pattern ->
@@ -102,10 +104,10 @@ class printer :
Format.formatter -> Parsetree.type_declaration -> unit
method type_def_list :
Format.formatter -> Parsetree.type_declaration list -> unit
+ method type_extension :
+ Format.formatter -> Parsetree.type_extension -> unit
method type_param :
- Format.formatter -> string Asttypes.loc option * Asttypes.variance -> unit
- method type_var_option :
- Format.formatter -> string Asttypes.loc option -> unit
+ Format.formatter -> Parsetree.core_type * Asttypes.variance -> unit
method type_with_label :
Format.formatter -> Asttypes.label * Parsetree.core_type -> unit
method tyvar : Format.formatter -> string -> unit
diff --git a/parsing/printast.ml b/parsing/printast.ml
index 5c4e8d74f1..70f90dea1d 100644
--- a/parsing/printast.ml
+++ b/parsing/printast.ml
@@ -157,8 +157,9 @@ let rec core_type i ppf x =
line i ppf "Ptyp_object %a\n" fmt_closed_flag c;
let i = i + 1 in
List.iter
- (fun (s, t) ->
- line i ppf "method %s" s;
+ (fun (s, attrs, t) ->
+ line i ppf "method %s\n" s;
+ attributes i ppf attrs;
core_type (i + 1) ppf t
)
l
@@ -227,6 +228,9 @@ and pattern i ppf x =
longident_loc i ppf li
| Ppat_unpack s ->
line i ppf "Ppat_unpack %a\n" fmt_string_loc s;
+ | Ppat_exception p ->
+ line i ppf "Ppat_exception\n";
+ pattern i ppf p
| Ppat_extension (s, arg) ->
line i ppf "Ppat_extension \"%s\"\n" s.txt;
payload i ppf arg
@@ -363,12 +367,7 @@ and value_description i ppf x =
core_type (i+1) ppf x.pval_type;
list (i+1) string ppf x.pval_prim
-and type_parameter i ppf (x, _variance) =
- match x with
- | Some x ->
- string_loc i ppf x
- | None ->
- string i ppf "_"
+and type_parameter i ppf (x, _variance) = core_type i ppf x
and type_declaration i ppf x =
line i ppf "type_declaration %a %a\n" fmt_string_loc x.ptype_name
@@ -414,6 +413,37 @@ and type_kind i ppf x =
| Ptype_record l ->
line i ppf "Ptype_record\n";
list (i+1) label_decl ppf l;
+ | Ptype_open ->
+ line i ppf "Ptype_open\n";
+
+and type_extension i ppf x =
+ line i ppf "type_extension\n";
+ attributes i ppf x.ptyext_attributes;
+ let i = i+1 in
+ line i ppf "ptyext_path = %a\n" fmt_longident_loc x.ptyext_path;
+ line i ppf "ptyext_params =\n";
+ list (i+1) type_parameter ppf x.ptyext_params;
+ line i ppf "ptyext_constructors =\n";
+ list (i+1) extension_constructor ppf x.ptyext_constructors;
+ line i ppf "ptyext_private = %a\n" fmt_private_flag x.ptyext_private;
+
+and extension_constructor i ppf x =
+ line i ppf "extension_constructor %a\n" fmt_location x.pext_loc;
+ attributes i ppf x.pext_attributes;
+ let i = i + 1 in
+ line i ppf "pext_name = \"%s\"\n" x.pext_name.txt;
+ line i ppf "pext_kind =\n";
+ extension_constructor_kind (i + 1) ppf x.pext_kind;
+
+and extension_constructor_kind i ppf x =
+ match x with
+ Pext_decl(a, r) ->
+ line i ppf "Pext_decl\n";
+ constructor_arguments (i+1) ppf a;
+ option (i+1) core_type ppf r;
+ | Pext_rebind li ->
+ line i ppf "Pext_rebind\n";
+ line (i+1) ppf "%a\n" fmt_longident_loc li;
and class_type i ppf x =
line i ppf "class_type %a\n" fmt_location x.pcty_loc;
@@ -459,6 +489,9 @@ 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_extension (s, arg) ->
line i ppf "Pctf_extension \"%s\"\n" s.txt;
payload i ppf arg
@@ -469,7 +502,7 @@ and class_description i ppf x =
let i = i+1 in
line i ppf "pci_virt = %a\n" fmt_virtual_flag x.pci_virt;
line i ppf "pci_params =\n";
- cl_type_parameters (i+1) ppf x.pci_params;
+ list (i+1) type_parameter ppf x.pci_params;
line i ppf "pci_name = %a\n" fmt_string_loc x.pci_name;
line i ppf "pci_expr =\n";
class_type (i+1) ppf x.pci_expr;
@@ -480,7 +513,7 @@ and class_type_declaration i ppf x =
let i = i+1 in
line i ppf "pci_virt = %a\n" fmt_virtual_flag x.pci_virt;
line i ppf "pci_params =\n";
- cl_type_parameters (i+1) ppf x.pci_params;
+ list (i+1) type_parameter ppf x.pci_params;
line i ppf "pci_name = %a\n" fmt_string_loc x.pci_name;
line i ppf "pci_expr =\n";
class_type (i+1) ppf x.pci_expr;
@@ -547,6 +580,9 @@ 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_extension (s, arg) ->
line i ppf "Pcf_extension \"%s\"\n" s.txt;
payload i ppf arg
@@ -565,7 +601,7 @@ and class_declaration i ppf x =
let i = i+1 in
line i ppf "pci_virt = %a\n" fmt_virtual_flag x.pci_virt;
line i ppf "pci_params =\n";
- cl_type_parameters (i+1) ppf x.pci_params;
+ list (i+1) type_parameter ppf x.pci_params;
line i ppf "pci_name = %a\n" fmt_string_loc x.pci_name;
line i ppf "pci_expr =\n";
class_expr (i+1) ppf x.pci_expr;
@@ -607,9 +643,12 @@ and signature_item i ppf x =
| Psig_type (l) ->
line i ppf "Psig_type\n";
list i type_declaration ppf l;
- | Psig_exception cd ->
+ | Psig_typext te ->
+ line i ppf "Psig_typext\n";
+ type_extension i ppf te
+ | Psig_exception ext ->
line i ppf "Psig_exception\n";
- constructor_decl i ppf cd;
+ extension_constructor i ppf ext;
| Psig_module pmd ->
line i ppf "Psig_module %a\n" fmt_string_loc pmd.pmd_name;
attributes i ppf pmd.pmd_attributes;
@@ -712,14 +751,12 @@ and structure_item i ppf x =
| Pstr_type l ->
line i ppf "Pstr_type\n";
list i type_declaration ppf l;
- | Pstr_exception cd ->
+ | Pstr_typext te ->
+ line i ppf "Pstr_typext\n";
+ type_extension i ppf te
+ | Pstr_exception ext ->
line i ppf "Pstr_exception\n";
- constructor_decl i ppf cd;
- | Pstr_exn_rebind er ->
- line i ppf "Pstr_exn_rebind\n";
- attributes i ppf er.pexrb_attributes;
- line (i+1) ppf "%a\n" fmt_string_loc er.pexrb_name;
- line (i+1) ppf "%a\n" fmt_longident_loc er.pexrb_lid
+ extension_constructor i ppf ext;
| Pstr_module x ->
line i ppf "Pstr_module\n";
module_binding i ppf x
@@ -771,14 +808,15 @@ and core_type_x_core_type_x_location i ppf (ct1, ct2, l) =
and constructor_decl i ppf
{pcd_name; pcd_args; pcd_res; pcd_loc; pcd_attributes} =
line i ppf "%a\n" fmt_location pcd_loc;
- attributes i ppf pcd_attributes;
line (i+1) ppf "%a\n" fmt_string_loc pcd_name;
- begin match pcd_args with
- | Pcstr_tuple l -> list (i+1) core_type ppf l;
- | Pcstr_record l -> list (i+1) label_decl ppf l
- end;
+ attributes i ppf pcd_attributes;
+ constructor_arguments (i+1) ppf pcd_args;
option (i+1) core_type ppf pcd_res
+and constructor_arguments i ppf = function
+ | Pcstr_tuple l -> list i core_type ppf l;
+ | Pcstr_record l -> list i label_decl ppf l
+
and label_decl i ppf {pld_name; pld_mutable; pld_type; pld_loc; pld_attributes}=
line i ppf "%a\n" fmt_location pld_loc;
attributes i ppf pld_attributes;
@@ -786,13 +824,6 @@ and label_decl i ppf {pld_name; pld_mutable; pld_type; pld_loc; pld_attributes}=
line (i+1) ppf "%a" fmt_string_loc pld_name;
core_type (i+1) ppf pld_type
-and cl_type_parameters i ppf l =
- line i ppf "<params>\n";
- list (i+1) cl_type_parameter ppf l;
-
-and cl_type_parameter i ppf (x, _variance) =
- string_loc i ppf x
-
and longident_x_pattern i ppf (li, p) =
line i ppf "%a\n" fmt_longident_loc li;
pattern (i+1) ppf p;
@@ -826,8 +857,9 @@ and label_x_expression i ppf (l,e) =
and label_x_bool_x_core_type_list i ppf x =
match x with
- Rtag (l, b, ctl) ->
+ Rtag (l, attrs, b, ctl) ->
line i ppf "Rtag \"%s\" %s\n" l (string_of_bool b);
+ attributes (i+1) ppf attrs;
list (i+1) core_type ppf ctl
| Rinherit (ct) ->
line i ppf "Rinherit\n";
@@ -841,15 +873,15 @@ let rec toplevel_phrase i ppf x =
structure (i+1) ppf s;
| Ptop_dir (s, da) ->
line i ppf "Ptop_dir \"%s\"\n" s;
- list i directive_argument ppf da;
+ directive_argument i ppf da;
and directive_argument i ppf x =
match x with
+ | Pdir_none -> line i ppf "Pdir_none\n"
| Pdir_string (s) -> line i ppf "Pdir_string \"%s\"\n" s;
| Pdir_int (i) -> line i ppf "Pdir_int %d\n" i;
| Pdir_ident (li) -> line i ppf "Pdir_ident %a\n" fmt_longident li;
| Pdir_bool (b) -> line i ppf "Pdir_bool %s\n" (string_of_bool b);
- | Pdir_keyword s -> line i ppf "Pdir_keyword %s\n" s;
;;
let interface ppf x = list 0 signature_item ppf x;;
diff --git a/stdlib/.depend b/stdlib/.depend
index e5b65ad513..e3a0a671d1 100644
--- a/stdlib/.depend
+++ b/stdlib/.depend
@@ -2,7 +2,11 @@ arg.cmi :
array.cmi :
arrayLabels.cmi :
buffer.cmi :
+bytes.cmi :
+bytesLabels.cmi :
callback.cmi :
+camlinternalFormat.cmi : camlinternalFormatBasics.cmi buffer.cmi
+camlinternalFormatBasics.cmi :
camlinternalLazy.cmi :
camlinternalMod.cmi : obj.cmi
camlinternalOO.cmi : obj.cmi
@@ -27,16 +31,17 @@ nativeint.cmi :
obj.cmi : int32.cmi
oo.cmi : camlinternalOO.cmi
parsing.cmi : obj.cmi lexing.cmi
-pervasives.cmi :
+pervasives.cmi : camlinternalFormatBasics.cmi
printexc.cmi :
-printf.cmi : obj.cmi buffer.cmi
+printf.cmi : buffer.cmi
queue.cmi :
random.cmi : nativeint.cmi int64.cmi int32.cmi
scanf.cmi : pervasives.cmi
set.cmi :
sort.cmi :
stack.cmi :
-stdLabels.cmi : stringLabels.cmi listLabels.cmi arrayLabels.cmi
+stdLabels.cmi : stringLabels.cmi listLabels.cmi bytesLabels.cmi \
+ arrayLabels.cmi
stream.cmi :
string.cmi :
stringLabels.cmi :
@@ -50,10 +55,20 @@ array.cmo : array.cmi
array.cmx : array.cmi
arrayLabels.cmo : array.cmi arrayLabels.cmi
arrayLabels.cmx : array.cmx arrayLabels.cmi
-buffer.cmo : sys.cmi string.cmi buffer.cmi
-buffer.cmx : sys.cmx string.cmx buffer.cmi
+buffer.cmo : sys.cmi string.cmi bytes.cmi buffer.cmi
+buffer.cmx : sys.cmx string.cmx bytes.cmx buffer.cmi
+bytes.cmo : pervasives.cmi list.cmi char.cmi bytes.cmi
+bytes.cmx : pervasives.cmx list.cmx char.cmx bytes.cmi
+bytesLabels.cmo : bytes.cmi bytesLabels.cmi
+bytesLabels.cmx : bytes.cmx bytesLabels.cmi
callback.cmo : obj.cmi callback.cmi
callback.cmx : obj.cmx callback.cmi
+camlinternalFormat.cmo : sys.cmi string.cmi char.cmi \
+ camlinternalFormatBasics.cmi bytes.cmi buffer.cmi camlinternalFormat.cmi
+camlinternalFormat.cmx : sys.cmx string.cmx char.cmx \
+ camlinternalFormatBasics.cmx bytes.cmx buffer.cmx camlinternalFormat.cmi
+camlinternalFormatBasics.cmo : camlinternalFormatBasics.cmi
+camlinternalFormatBasics.cmx : camlinternalFormatBasics.cmi
camlinternalLazy.cmo : obj.cmi camlinternalLazy.cmi
camlinternalLazy.cmx : obj.cmx camlinternalLazy.cmi
camlinternalMod.cmo : obj.cmi camlinternalOO.cmi array.cmi \
@@ -68,20 +83,22 @@ char.cmo : char.cmi
char.cmx : char.cmi
complex.cmo : complex.cmi
complex.cmx : complex.cmi
-digest.cmo : string.cmi char.cmi digest.cmi
-digest.cmx : string.cmx char.cmx digest.cmi
+digest.cmo : string.cmi char.cmi bytes.cmi digest.cmi
+digest.cmx : string.cmx char.cmx bytes.cmx digest.cmi
filename.cmo : sys.cmi string.cmi random.cmi printf.cmi lazy.cmi buffer.cmi \
filename.cmi
filename.cmx : sys.cmx string.cmx random.cmx printf.cmx lazy.cmx buffer.cmx \
filename.cmi
-format.cmo : string.cmi printf.cmi pervasives.cmi obj.cmi list.cmi \
- buffer.cmi format.cmi
-format.cmx : string.cmx printf.cmx pervasives.cmx obj.cmx list.cmx \
- buffer.cmx format.cmi
+format.cmo : string.cmi pervasives.cmi camlinternalFormatBasics.cmi \
+ camlinternalFormat.cmi buffer.cmi format.cmi
+format.cmx : string.cmx pervasives.cmx camlinternalFormatBasics.cmx \
+ camlinternalFormat.cmx buffer.cmx format.cmi
gc.cmo : sys.cmi printf.cmi gc.cmi
gc.cmx : sys.cmx printf.cmx gc.cmi
-genlex.cmo : string.cmi stream.cmi list.cmi hashtbl.cmi char.cmi genlex.cmi
-genlex.cmx : string.cmx stream.cmx list.cmx hashtbl.cmx char.cmx genlex.cmi
+genlex.cmo : string.cmi stream.cmi list.cmi hashtbl.cmi char.cmi bytes.cmi \
+ genlex.cmi
+genlex.cmx : string.cmx stream.cmx list.cmx hashtbl.cmx char.cmx bytes.cmx \
+ genlex.cmi
hashtbl.cmo : sys.cmi string.cmi random.cmi obj.cmi lazy.cmi array.cmi \
hashtbl.cmi
hashtbl.cmx : sys.cmx string.cmx random.cmx obj.cmx lazy.cmx array.cmx \
@@ -92,16 +109,16 @@ int64.cmo : pervasives.cmi int64.cmi
int64.cmx : pervasives.cmx int64.cmi
lazy.cmo : obj.cmi camlinternalLazy.cmi lazy.cmi
lazy.cmx : obj.cmx camlinternalLazy.cmx lazy.cmi
-lexing.cmo : sys.cmi string.cmi array.cmi lexing.cmi
-lexing.cmx : sys.cmx string.cmx array.cmx lexing.cmi
+lexing.cmo : sys.cmi string.cmi bytes.cmi array.cmi lexing.cmi
+lexing.cmx : sys.cmx string.cmx bytes.cmx array.cmx lexing.cmi
list.cmo : list.cmi
list.cmx : list.cmi
listLabels.cmo : list.cmi listLabels.cmi
listLabels.cmx : list.cmx listLabels.cmi
map.cmo : map.cmi
map.cmx : map.cmi
-marshal.cmo : string.cmi marshal.cmi
-marshal.cmx : string.cmx marshal.cmi
+marshal.cmo : bytes.cmi marshal.cmi
+marshal.cmx : bytes.cmx marshal.cmi
moreLabels.cmo : set.cmi map.cmi hashtbl.cmi moreLabels.cmi
moreLabels.cmx : set.cmx map.cmx hashtbl.cmx moreLabels.cmi
nativeint.cmo : sys.cmi pervasives.cmi nativeint.cmi
@@ -112,13 +129,15 @@ oo.cmo : camlinternalOO.cmi oo.cmi
oo.cmx : camlinternalOO.cmx oo.cmi
parsing.cmo : obj.cmi lexing.cmi array.cmi parsing.cmi
parsing.cmx : obj.cmx lexing.cmx array.cmx parsing.cmi
-pervasives.cmo : pervasives.cmi
-pervasives.cmx : pervasives.cmi
-printexc.cmo : printf.cmi obj.cmi buffer.cmi array.cmi printexc.cmi
-printexc.cmx : printf.cmx obj.cmx buffer.cmx array.cmx printexc.cmi
-printf.cmo : string.cmi obj.cmi list.cmi char.cmi buffer.cmi array.cmi \
+pervasives.cmo : camlinternalFormatBasics.cmi pervasives.cmi
+pervasives.cmx : camlinternalFormatBasics.cmx pervasives.cmi
+printexc.cmo : printf.cmi pervasives.cmi obj.cmi buffer.cmi array.cmi \
+ printexc.cmi
+printexc.cmx : printf.cmx pervasives.cmx obj.cmx buffer.cmx array.cmx \
+ printexc.cmi
+printf.cmo : camlinternalFormatBasics.cmi camlinternalFormat.cmi buffer.cmi \
printf.cmi
-printf.cmx : string.cmx obj.cmx list.cmx char.cmx buffer.cmx array.cmx \
+printf.cmx : camlinternalFormatBasics.cmx camlinternalFormat.cmx buffer.cmx \
printf.cmi
queue.cmo : obj.cmi queue.cmi
queue.cmx : obj.cmx queue.cmi
@@ -126,26 +145,28 @@ random.cmo : string.cmi pervasives.cmi nativeint.cmi int64.cmi int32.cmi \
digest.cmi char.cmi array.cmi random.cmi
random.cmx : string.cmx pervasives.cmx nativeint.cmx int64.cmx int32.cmx \
digest.cmx char.cmx array.cmx random.cmi
-scanf.cmo : string.cmi printf.cmi pervasives.cmi obj.cmi list.cmi \
- hashtbl.cmi buffer.cmi array.cmi scanf.cmi
-scanf.cmx : string.cmx printf.cmx pervasives.cmx obj.cmx list.cmx \
- hashtbl.cmx buffer.cmx array.cmx scanf.cmi
+scanf.cmo : string.cmi printf.cmi pervasives.cmi list.cmi \
+ camlinternalFormatBasics.cmi camlinternalFormat.cmi bytes.cmi buffer.cmi \
+ scanf.cmi
+scanf.cmx : string.cmx printf.cmx pervasives.cmx list.cmx \
+ camlinternalFormatBasics.cmx camlinternalFormat.cmx bytes.cmx buffer.cmx \
+ scanf.cmi
set.cmo : list.cmi set.cmi
set.cmx : list.cmx set.cmi
sort.cmo : array.cmi sort.cmi
sort.cmx : array.cmx sort.cmi
stack.cmo : list.cmi stack.cmi
stack.cmx : list.cmx stack.cmi
-stdLabels.cmo : stringLabels.cmi listLabels.cmi arrayLabels.cmi \
- stdLabels.cmi
-stdLabels.cmx : stringLabels.cmx listLabels.cmx arrayLabels.cmx \
- stdLabels.cmi
+stdLabels.cmo : stringLabels.cmi listLabels.cmi bytesLabels.cmi \
+ arrayLabels.cmi stdLabels.cmi
+stdLabels.cmx : stringLabels.cmx listLabels.cmx bytesLabels.cmx \
+ arrayLabels.cmx stdLabels.cmi
std_exit.cmo :
std_exit.cmx :
-stream.cmo : string.cmi obj.cmi list.cmi lazy.cmi stream.cmi
-stream.cmx : string.cmx obj.cmx list.cmx lazy.cmx stream.cmi
-string.cmo : pervasives.cmi list.cmi char.cmi string.cmi
-string.cmx : pervasives.cmx list.cmx char.cmx string.cmi
+stream.cmo : string.cmi obj.cmi list.cmi lazy.cmi bytes.cmi stream.cmi
+stream.cmx : string.cmx obj.cmx list.cmx lazy.cmx bytes.cmx stream.cmi
+string.cmo : pervasives.cmi obj.cmi bytes.cmi string.cmi
+string.cmx : pervasives.cmx obj.cmx bytes.cmx string.cmi
stringLabels.cmo : string.cmi stringLabels.cmi
stringLabels.cmx : string.cmx stringLabels.cmi
sys.cmo : sys.cmi
@@ -160,10 +181,20 @@ array.cmo : array.cmi
array.p.cmx : array.cmi
arrayLabels.cmo : array.cmi arrayLabels.cmi
arrayLabels.p.cmx : array.p.cmx arrayLabels.cmi
-buffer.cmo : sys.cmi string.cmi buffer.cmi
-buffer.p.cmx : sys.p.cmx string.p.cmx buffer.cmi
+buffer.cmo : sys.cmi string.cmi bytes.cmi buffer.cmi
+buffer.p.cmx : sys.p.cmx string.p.cmx bytes.p.cmx buffer.cmi
+bytes.cmo : pervasives.cmi list.cmi char.cmi bytes.cmi
+bytes.p.cmx : pervasives.p.cmx list.p.cmx char.p.cmx bytes.cmi
+bytesLabels.cmo : bytes.cmi bytesLabels.cmi
+bytesLabels.p.cmx : bytes.p.cmx bytesLabels.cmi
callback.cmo : obj.cmi callback.cmi
callback.p.cmx : obj.p.cmx callback.cmi
+camlinternalFormat.cmo : sys.cmi string.cmi char.cmi \
+ camlinternalFormatBasics.cmi bytes.cmi buffer.cmi camlinternalFormat.cmi
+camlinternalFormat.p.cmx : sys.p.cmx string.p.cmx char.p.cmx \
+ camlinternalFormatBasics.p.cmx bytes.p.cmx buffer.p.cmx camlinternalFormat.cmi
+camlinternalFormatBasics.cmo : camlinternalFormatBasics.cmi
+camlinternalFormatBasics.p.cmx : camlinternalFormatBasics.cmi
camlinternalLazy.cmo : obj.cmi camlinternalLazy.cmi
camlinternalLazy.p.cmx : obj.p.cmx camlinternalLazy.cmi
camlinternalMod.cmo : obj.cmi camlinternalOO.cmi array.cmi \
@@ -178,20 +209,22 @@ char.cmo : char.cmi
char.p.cmx : char.cmi
complex.cmo : complex.cmi
complex.p.cmx : complex.cmi
-digest.cmo : string.cmi char.cmi digest.cmi
-digest.p.cmx : string.p.cmx char.p.cmx digest.cmi
+digest.cmo : string.cmi char.cmi bytes.cmi digest.cmi
+digest.p.cmx : string.p.cmx char.p.cmx bytes.p.cmx digest.cmi
filename.cmo : sys.cmi string.cmi random.cmi printf.cmi lazy.cmi buffer.cmi \
filename.cmi
filename.p.cmx : sys.p.cmx string.p.cmx random.p.cmx printf.p.cmx lazy.p.cmx buffer.p.cmx \
filename.cmi
-format.cmo : string.cmi printf.cmi pervasives.cmi obj.cmi list.cmi \
- buffer.cmi format.cmi
-format.p.cmx : string.p.cmx printf.p.cmx pervasives.p.cmx obj.p.cmx list.p.cmx \
- buffer.p.cmx format.cmi
+format.cmo : string.cmi pervasives.cmi camlinternalFormatBasics.cmi \
+ camlinternalFormat.cmi buffer.cmi format.cmi
+format.p.cmx : string.p.cmx pervasives.p.cmx camlinternalFormatBasics.p.cmx \
+ camlinternalFormat.p.cmx buffer.p.cmx format.cmi
gc.cmo : sys.cmi printf.cmi gc.cmi
gc.p.cmx : sys.p.cmx printf.p.cmx gc.cmi
-genlex.cmo : string.cmi stream.cmi list.cmi hashtbl.cmi char.cmi genlex.cmi
-genlex.p.cmx : string.p.cmx stream.p.cmx list.p.cmx hashtbl.p.cmx char.p.cmx genlex.cmi
+genlex.cmo : string.cmi stream.cmi list.cmi hashtbl.cmi char.cmi bytes.cmi \
+ genlex.cmi
+genlex.p.cmx : string.p.cmx stream.p.cmx list.p.cmx hashtbl.p.cmx char.p.cmx bytes.p.cmx \
+ genlex.cmi
hashtbl.cmo : sys.cmi string.cmi random.cmi obj.cmi lazy.cmi array.cmi \
hashtbl.cmi
hashtbl.p.cmx : sys.p.cmx string.p.cmx random.p.cmx obj.p.cmx lazy.p.cmx array.p.cmx \
@@ -202,16 +235,16 @@ int64.cmo : pervasives.cmi int64.cmi
int64.p.cmx : pervasives.p.cmx int64.cmi
lazy.cmo : obj.cmi camlinternalLazy.cmi lazy.cmi
lazy.p.cmx : obj.p.cmx camlinternalLazy.p.cmx lazy.cmi
-lexing.cmo : sys.cmi string.cmi array.cmi lexing.cmi
-lexing.p.cmx : sys.p.cmx string.p.cmx array.p.cmx lexing.cmi
+lexing.cmo : sys.cmi string.cmi bytes.cmi array.cmi lexing.cmi
+lexing.p.cmx : sys.p.cmx string.p.cmx bytes.p.cmx array.p.cmx lexing.cmi
list.cmo : list.cmi
list.p.cmx : list.cmi
listLabels.cmo : list.cmi listLabels.cmi
listLabels.p.cmx : list.p.cmx listLabels.cmi
map.cmo : map.cmi
map.p.cmx : map.cmi
-marshal.cmo : string.cmi marshal.cmi
-marshal.p.cmx : string.p.cmx marshal.cmi
+marshal.cmo : bytes.cmi marshal.cmi
+marshal.p.cmx : bytes.p.cmx marshal.cmi
moreLabels.cmo : set.cmi map.cmi hashtbl.cmi moreLabels.cmi
moreLabels.p.cmx : set.p.cmx map.p.cmx hashtbl.p.cmx moreLabels.cmi
nativeint.cmo : sys.cmi pervasives.cmi nativeint.cmi
@@ -222,13 +255,15 @@ oo.cmo : camlinternalOO.cmi oo.cmi
oo.p.cmx : camlinternalOO.p.cmx oo.cmi
parsing.cmo : obj.cmi lexing.cmi array.cmi parsing.cmi
parsing.p.cmx : obj.p.cmx lexing.p.cmx array.p.cmx parsing.cmi
-pervasives.cmo : pervasives.cmi
-pervasives.p.cmx : pervasives.cmi
-printexc.cmo : printf.cmi obj.cmi buffer.cmi array.cmi printexc.cmi
-printexc.p.cmx : printf.p.cmx obj.p.cmx buffer.p.cmx array.p.cmx printexc.cmi
-printf.cmo : string.cmi obj.cmi list.cmi char.cmi buffer.cmi array.cmi \
+pervasives.cmo : camlinternalFormatBasics.cmi pervasives.cmi
+pervasives.p.cmx : camlinternalFormatBasics.p.cmx pervasives.cmi
+printexc.cmo : printf.cmi pervasives.cmi obj.cmi buffer.cmi array.cmi \
+ printexc.cmi
+printexc.p.cmx : printf.p.cmx pervasives.p.cmx obj.p.cmx buffer.p.cmx array.p.cmx \
+ printexc.cmi
+printf.cmo : camlinternalFormatBasics.cmi camlinternalFormat.cmi buffer.cmi \
printf.cmi
-printf.p.cmx : string.p.cmx obj.p.cmx list.p.cmx char.p.cmx buffer.p.cmx array.p.cmx \
+printf.p.cmx : camlinternalFormatBasics.p.cmx camlinternalFormat.p.cmx buffer.p.cmx \
printf.cmi
queue.cmo : obj.cmi queue.cmi
queue.p.cmx : obj.p.cmx queue.cmi
@@ -236,26 +271,28 @@ random.cmo : string.cmi pervasives.cmi nativeint.cmi int64.cmi int32.cmi \
digest.cmi char.cmi array.cmi random.cmi
random.p.cmx : string.p.cmx pervasives.p.cmx nativeint.p.cmx int64.p.cmx int32.p.cmx \
digest.p.cmx char.p.cmx array.p.cmx random.cmi
-scanf.cmo : string.cmi printf.cmi pervasives.cmi obj.cmi list.cmi \
- hashtbl.cmi buffer.cmi array.cmi scanf.cmi
-scanf.p.cmx : string.p.cmx printf.p.cmx pervasives.p.cmx obj.p.cmx list.p.cmx \
- hashtbl.p.cmx buffer.p.cmx array.p.cmx scanf.cmi
+scanf.cmo : string.cmi printf.cmi pervasives.cmi list.cmi \
+ camlinternalFormatBasics.cmi camlinternalFormat.cmi bytes.cmi buffer.cmi \
+ scanf.cmi
+scanf.p.cmx : string.p.cmx printf.p.cmx pervasives.p.cmx list.p.cmx \
+ camlinternalFormatBasics.p.cmx camlinternalFormat.p.cmx bytes.p.cmx buffer.p.cmx \
+ scanf.cmi
set.cmo : list.cmi set.cmi
set.p.cmx : list.p.cmx set.cmi
sort.cmo : array.cmi sort.cmi
sort.p.cmx : array.p.cmx sort.cmi
stack.cmo : list.cmi stack.cmi
stack.p.cmx : list.p.cmx stack.cmi
-stdLabels.cmo : stringLabels.cmi listLabels.cmi arrayLabels.cmi \
- stdLabels.cmi
-stdLabels.p.cmx : stringLabels.p.cmx listLabels.p.cmx arrayLabels.p.cmx \
- stdLabels.cmi
+stdLabels.cmo : stringLabels.cmi listLabels.cmi bytesLabels.cmi \
+ arrayLabels.cmi stdLabels.cmi
+stdLabels.p.cmx : stringLabels.p.cmx listLabels.p.cmx bytesLabels.p.cmx \
+ arrayLabels.p.cmx stdLabels.cmi
std_exit.cmo :
std_exit.p.cmx :
-stream.cmo : string.cmi obj.cmi list.cmi lazy.cmi stream.cmi
-stream.p.cmx : string.p.cmx obj.p.cmx list.p.cmx lazy.p.cmx stream.cmi
-string.cmo : pervasives.cmi list.cmi char.cmi string.cmi
-string.p.cmx : pervasives.p.cmx list.p.cmx char.p.cmx string.cmi
+stream.cmo : string.cmi obj.cmi list.cmi lazy.cmi bytes.cmi stream.cmi
+stream.p.cmx : string.p.cmx obj.p.cmx list.p.cmx lazy.p.cmx bytes.p.cmx stream.cmi
+string.cmo : pervasives.cmi obj.cmi bytes.cmi string.cmi
+string.p.cmx : pervasives.p.cmx obj.p.cmx bytes.p.cmx string.cmi
stringLabels.cmo : string.cmi stringLabels.cmi
stringLabels.p.cmx : string.p.cmx stringLabels.cmi
sys.cmo : sys.cmi
diff --git a/stdlib/Compflags b/stdlib/Compflags
index d0938af89a..f393c4ec00 100755
--- a/stdlib/Compflags
+++ b/stdlib/Compflags
@@ -18,8 +18,11 @@ case $1 in
camlinternalOO.cmx|camlinternalOO.p.cmx) echo ' -inline 0';;
buffer.cmx|buffer.p.cmx) echo ' -inline 3';;
# make sure add_char is inlined (PR#5872)
- buffer.cm[io]|printf.cm[io]|format.cm[io]|scanf.cm[io]) echo ' -w A';;
+ buffer.cm[io]) echo ' -w A';;
+ camlinternalFormat.cm[io]) echo ' -w Ae';;
+ camlinternalFormatBasics*.cm[iox]) echo ' -nopervasives';;
+ printf.cm[io]|format.cm[io]|scanf.cm[io]) echo ' -w Ae';;
scanf.cmx|scanf.p.cmx) echo ' -inline 9';;
- *Labels.cm[ox]|*Labels.p.cmx) echo ' -nolabels -trans-mod';;
+ *Labels.cm[ox]|*Labels.p.cmx) echo ' -nolabels -no-alias-deps';;
*) echo ' ';;
esac
diff --git a/stdlib/Makefile.shared b/stdlib/Makefile.shared
index e4fee75d3c..54de337cb4 100755
--- a/stdlib/Makefile.shared
+++ b/stdlib/Makefile.shared
@@ -15,25 +15,27 @@ include ../config/Makefile
RUNTIME=../boot/ocamlrun
COMPILER=../ocamlc
CAMLC=$(RUNTIME) $(COMPILER)
-COMPFLAGS=-strict-sequence -w +33..39 -g -warn-error A -bin-annot -nostdlib
+COMPFLAGS=-strict-sequence -w +33..39 -g -warn-error A -bin-annot -nostdlib \
+ -safe-string
OPTCOMPILER=../ocamlopt
CAMLOPT=$(RUNTIME) $(OPTCOMPILER)
CAMLDEP=../boot/ocamlrun ../tools/ocamldep
-OBJS=pervasives.cmo $(OTHERS)
-OTHERS=array.cmo list.cmo char.cmo string.cmo sys.cmo \
+OBJS=camlinternalFormatBasics.cmo pervasives.cmo $(OTHERS)
+OTHERS=array.cmo list.cmo char.cmo bytes.cmo string.cmo sys.cmo \
sort.cmo marshal.cmo obj.cmo \
int32.cmo int64.cmo nativeint.cmo \
lexing.cmo parsing.cmo \
set.cmo map.cmo stack.cmo queue.cmo \
camlinternalLazy.cmo lazy.cmo stream.cmo \
- buffer.cmo printf.cmo \
+ buffer.cmo camlinternalFormat.cmo printf.cmo \
arg.cmo printexc.cmo gc.cmo \
digest.cmo random.cmo hashtbl.cmo format.cmo scanf.cmo callback.cmo \
camlinternalOO.cmo oo.cmo camlinternalMod.cmo \
genlex.cmo weak.cmo \
filename.cmo complex.cmo \
- arrayLabels.cmo listLabels.cmo stringLabels.cmo moreLabels.cmo stdLabels.cmo
+ arrayLabels.cmo listLabels.cmo bytesLabels.cmo \
+ stringLabels.cmo moreLabels.cmo stdLabels.cmo
all: stdlib.cma std_exit.cmo camlheader camlheader_ur
@@ -86,7 +88,7 @@ $(OBJS:.cmo=.cmx) std_exit.cmx: $(OPTCOMPILER)
$(OBJS:.cmo=.p.cmx) std_exit.p.cmx: $(OPTCOMPILER)
# Dependencies on Pervasives (not tracked by ocamldep)
-$(OBJS) std_exit.cmo: pervasives.cmi
+$(OTHERS) std_exit.cmo: pervasives.cmi
$(OTHERS:.cmo=.cmi) std_exit.cmi: pervasives.cmi
$(OBJS:.cmo=.cmx) std_exit.cmx: pervasives.cmi
$(OBJS:.cmo=.p.cmx) std_exit.p.cmx: pervasives.cmi
diff --git a/stdlib/StdlibModules b/stdlib/StdlibModules
index c5c8896ed0..a4552ad940 100644
--- a/stdlib/StdlibModules
+++ b/stdlib/StdlibModules
@@ -21,6 +21,8 @@ STDLIB_MODULES=\
array \
arrayLabels \
buffer \
+ bytes \
+ bytesLabels \
callback \
camlinternalLazy \
camlinternalMod \
diff --git a/stdlib/buffer.ml b/stdlib/buffer.ml
index 78a9e26116..2d6f691a27 100644
--- a/stdlib/buffer.ml
+++ b/stdlib/buffer.ml
@@ -14,41 +14,38 @@
(* Extensible buffers *)
type t =
- {mutable buffer : string;
+ {mutable buffer : bytes;
mutable position : int;
mutable length : int;
- initial_buffer : string}
+ initial_buffer : bytes}
let create n =
let n = if n < 1 then 1 else n in
let n = if n > Sys.max_string_length then Sys.max_string_length else n in
- let s = String.create n in
+ let s = Bytes.create n in
{buffer = s; position = 0; length = n; initial_buffer = s}
-let contents b = String.sub b.buffer 0 b.position
+let contents b = Bytes.sub_string b.buffer 0 b.position
+let to_bytes b = Bytes.sub b.buffer 0 b.position
let sub b ofs len =
if ofs < 0 || len < 0 || ofs > b.position - len
then invalid_arg "Buffer.sub"
- else begin
- let r = String.create len in
- String.unsafe_blit b.buffer ofs r 0 len;
- r
- end
+ else Bytes.sub_string b.buffer ofs len
;;
let blit src srcoff dst dstoff len =
if len < 0 || srcoff < 0 || srcoff > src.position - len
- || dstoff < 0 || dstoff > (String.length dst) - len
+ || dstoff < 0 || dstoff > (Bytes.length dst) - len
then invalid_arg "Buffer.blit"
else
- String.blit src.buffer srcoff dst dstoff len
+ Bytes.blit src.buffer srcoff dst dstoff len
;;
let nth b ofs =
if ofs < 0 || ofs >= b.position then
invalid_arg "Buffer.nth"
- else String.unsafe_get b.buffer ofs
+ else Bytes.unsafe_get b.buffer ofs
;;
let length b = b.position
@@ -57,7 +54,7 @@ let clear b = b.position <- 0
let reset b =
b.position <- 0; b.buffer <- b.initial_buffer;
- b.length <- String.length b.buffer
+ b.length <- Bytes.length b.buffer
let resize b more =
let len = b.length in
@@ -68,34 +65,39 @@ let resize b more =
then new_len := Sys.max_string_length
else failwith "Buffer.add: cannot grow buffer"
end;
- let new_buffer = String.create !new_len in
- String.blit b.buffer 0 new_buffer 0 b.position;
+ let new_buffer = Bytes.create !new_len in
+ Bytes.blit b.buffer 0 new_buffer 0 b.position;
b.buffer <- new_buffer;
b.length <- !new_len
let add_char b c =
let pos = b.position in
if pos >= b.length then resize b 1;
- String.unsafe_set b.buffer pos c;
+ Bytes.unsafe_set b.buffer pos c;
b.position <- pos + 1
-let add_substring b s offset len =
- if offset < 0 || len < 0 || offset > String.length s - len
- then invalid_arg "Buffer.add_substring";
+let add_subbytes b s offset len =
+ if offset < 0 || len < 0 || offset > Bytes.length s - len
+ then invalid_arg "Buffer.add_subbytes";
let new_position = b.position + len in
if new_position > b.length then resize b len;
- String.unsafe_blit s offset b.buffer b.position len;
+ Bytes.unsafe_blit s offset b.buffer b.position len;
b.position <- new_position
-let add_string b s =
- let len = String.length s in
+let add_substring b s offset len =
+ add_subbytes b (Bytes.unsafe_of_string s) offset len
+
+let add_bytes b s =
+ let len = Bytes.length s in
let new_position = b.position + len in
if new_position > b.length then resize b len;
- String.unsafe_blit s 0 b.buffer b.position len;
+ Bytes.unsafe_blit s 0 b.buffer b.position len;
b.position <- new_position
+let add_string b s = add_bytes b (Bytes.unsafe_of_string s)
+
let add_buffer b bs =
- add_substring b bs.buffer 0 bs.position
+ add_subbytes b bs.buffer 0 bs.position
let add_channel b ic len =
if len < 0 || len > Sys.max_string_length then (* PR#5004 *)
diff --git a/stdlib/buffer.mli b/stdlib/buffer.mli
index c50c98792b..855a061667 100644
--- a/stdlib/buffer.mli
+++ b/stdlib/buffer.mli
@@ -11,9 +11,9 @@
(* *)
(***********************************************************************)
-(** Extensible string buffers.
+(** Extensible buffers.
- This module implements string buffers that automatically expand
+ This module implements buffers that automatically expand
as necessary. It provides accumulative concatenation of strings
in quasi-linear time (instead of quadratic time when strings are
concatenated pairwise).
@@ -24,8 +24,8 @@ type t
val create : int -> t
(** [create n] returns a fresh buffer, initially empty.
- The [n] parameter is the initial size of the internal string
- that holds the buffer contents. That string is automatically
+ The [n] parameter is the initial size of the internal byte sequence
+ that holds the buffer contents. That byte sequence is automatically
reallocated when more than [n] characters are stored in the buffer,
but shrinks back to [n] characters when [reset] is called.
For best performance, [n] should be of the same order of magnitude
@@ -40,20 +40,24 @@ val contents : t -> string
(** Return a copy of the current contents of the buffer.
The buffer itself is unchanged. *)
+val to_bytes : t -> bytes
+(** Return a copy of the current contents of the buffer.
+ The buffer itself is unchanged. *)
+
val sub : t -> int -> int -> string
-(** [Buffer.sub b off len] returns (a copy of) the substring of the
+(** [Buffer.sub b off len] returns (a copy of) the bytes from the
current contents of the buffer [b] starting at offset [off] of length
[len] bytes. May raise [Invalid_argument] if out of bounds request. The
buffer itself is unaffected. *)
-val blit : t -> int -> string -> int -> int -> unit
+val blit : t -> int -> bytes -> int -> int -> unit
(** [Buffer.blit src srcoff dst dstoff len] copies [len] characters from
the current contents of the buffer [src], starting at offset [srcoff]
- to string [dst], starting at character [dstoff].
+ to [dst], starting at character [dstoff].
Raise [Invalid_argument] if [srcoff] and [len] do not designate a valid
- substring of [src], or if [dstoff] and [len] do not designate a valid
- substring of [dst].
+ range of [src], or if [dstoff] and [len] do not designate a valid
+ range of [dst].
@since 3.11.2
*)
@@ -68,8 +72,8 @@ val clear : t -> unit
(** Empty the buffer. *)
val reset : t -> unit
-(** Empty the buffer and deallocate the internal string holding the
- buffer contents, replacing it with the initial internal string
+(** Empty the buffer and deallocate the internal byte sequence holding the
+ buffer contents, replacing it with the initial internal byte sequence
of length [n] that was allocated by {!Buffer.create} [n].
For long-lived buffers that may have grown a lot, [reset] allows
faster reclamation of the space used by the buffer. *)
@@ -80,10 +84,17 @@ val add_char : t -> char -> unit
val add_string : t -> string -> unit
(** [add_string b s] appends the string [s] at the end of the buffer [b]. *)
+val add_bytes : t -> bytes -> unit
+(** [add_string b s] appends the string [s] at the end of the buffer [b]. *)
+
val add_substring : t -> string -> int -> int -> unit
(** [add_substring b s ofs len] takes [len] characters from offset
[ofs] in string [s] and appends them at the end of the buffer [b]. *)
+val add_subbytes : t -> bytes -> int -> int -> unit
+(** [add_substring b s ofs len] takes [len] characters from offset
+ [ofs] in byte sequence [s] and appends them at the end of the buffer [b]. *)
+
val add_substitute : t -> (string -> string) -> string -> unit
(** [add_substitute b f s] appends the string pattern [s] at the end
of the buffer [b] with substitution.
diff --git a/stdlib/bytes.ml b/stdlib/bytes.ml
new file mode 100644
index 0000000000..cfcd1ec05e
--- /dev/null
+++ b/stdlib/bytes.ml
@@ -0,0 +1,226 @@
+(***********************************************************************)
+(* *)
+(* 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 Library General Public License, with *)
+(* the special exception on linking described in file ../LICENSE. *)
+(* *)
+(***********************************************************************)
+
+(* Byte sequence operations *)
+
+external length : bytes -> int = "%string_length"
+external get : bytes -> int -> char = "%string_safe_get"
+external set : bytes -> int -> char -> unit = "%string_safe_set"
+external create : int -> bytes = "caml_create_string"
+external unsafe_get : bytes -> int -> char = "%string_unsafe_get"
+external unsafe_set : bytes -> int -> char -> unit = "%string_unsafe_set"
+external unsafe_blit : bytes -> int -> bytes -> int -> int -> unit
+ = "caml_blit_string" "noalloc"
+external unsafe_fill : bytes -> int -> int -> char -> unit
+ = "caml_fill_string" "noalloc"
+external unsafe_to_string : bytes -> string = "%identity"
+external unsafe_of_string : string -> bytes = "%identity"
+
+let make n c =
+ let s = create n in
+ unsafe_fill s 0 n c;
+ s
+
+let init n f =
+ let s = create n in
+ for i = 0 to n - 1 do
+ unsafe_set s i (f i)
+ done;
+ s
+
+let empty = create 0;;
+
+let copy s =
+ let len = length s in
+ let r = create len in
+ unsafe_blit s 0 r 0 len;
+ r
+
+let to_string b = unsafe_to_string (copy b)
+let of_string s = copy (unsafe_of_string s)
+
+let sub s ofs len =
+ if ofs < 0 || len < 0 || ofs > length s - len
+ then invalid_arg "Bytes.sub"
+ else begin
+ let r = create len in
+ unsafe_blit s ofs r 0 len;
+ r
+ end
+
+let sub_string b ofs len = unsafe_to_string (sub b ofs len)
+
+let fill s ofs len c =
+ if ofs < 0 || len < 0 || ofs > length s - len
+ then invalid_arg "Bytes.fill"
+ else unsafe_fill s ofs len c
+
+let blit s1 ofs1 s2 ofs2 len =
+ if len < 0 || ofs1 < 0 || ofs1 > length s1 - len
+ || ofs2 < 0 || ofs2 > length s2 - len
+ then invalid_arg "Bytes.blit"
+ else unsafe_blit s1 ofs1 s2 ofs2 len
+
+let iter f a =
+ for i = 0 to length a - 1 do f(unsafe_get a i) done
+
+let iteri f a =
+ for i = 0 to length a - 1 do f i (unsafe_get a i) done
+
+let concat sep l =
+ match l with
+ [] -> empty
+ | hd :: tl ->
+ let num = ref 0 and len = ref 0 in
+ List.iter (fun s -> incr num; len := !len + length s) l;
+ let r = create (!len + length sep * (!num - 1)) in
+ unsafe_blit hd 0 r 0 (length hd);
+ let pos = ref(length hd) in
+ List.iter
+ (fun s ->
+ unsafe_blit sep 0 r !pos (length sep);
+ pos := !pos + length sep;
+ unsafe_blit s 0 r !pos (length s);
+ pos := !pos + length s)
+ tl;
+ r
+
+external is_printable: char -> bool = "caml_is_printable"
+external char_code: char -> int = "%identity"
+external char_chr: int -> char = "%identity"
+
+let is_space = function
+ | ' ' | '\012' | '\n' | '\r' | '\t' -> true
+ | _ -> false
+
+let trim s =
+ let len = length s in
+ let i = ref 0 in
+ while !i < len && is_space (unsafe_get s !i) do
+ incr i
+ done;
+ let j = ref (len - 1) in
+ while !j >= !i && is_space (unsafe_get s !j) do
+ decr j
+ done;
+ if !j >= !i then
+ sub s !i (!j - !i + 1)
+ else
+ empty
+
+let escaped s =
+ let n = ref 0 in
+ for i = 0 to length s - 1 do
+ n := !n +
+ (match unsafe_get s i with
+ | '"' | '\\' | '\n' | '\t' | '\r' | '\b' -> 2
+ | c -> if is_printable c then 1 else 4)
+ done;
+ if !n = length s then copy s else begin
+ let s' = create !n in
+ n := 0;
+ for i = 0 to length s - 1 do
+ begin match unsafe_get s i with
+ | ('"' | '\\') as c ->
+ unsafe_set s' !n '\\'; incr n; unsafe_set s' !n c
+ | '\n' ->
+ unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'n'
+ | '\t' ->
+ unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 't'
+ | '\r' ->
+ unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'r'
+ | '\b' ->
+ unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'b'
+ | c ->
+ if is_printable c then
+ unsafe_set s' !n c
+ else begin
+ let a = char_code c in
+ unsafe_set s' !n '\\';
+ incr n;
+ unsafe_set s' !n (char_chr (48 + a / 100));
+ incr n;
+ unsafe_set s' !n (char_chr (48 + (a / 10) mod 10));
+ incr n;
+ unsafe_set s' !n (char_chr (48 + a mod 10))
+ end
+ end;
+ incr n
+ done;
+ s'
+ end
+
+let map f s =
+ let l = length s in
+ if l = 0 then s else begin
+ let r = create l in
+ for i = 0 to l - 1 do unsafe_set r i (f (unsafe_get s i)) done;
+ r
+ end
+
+let mapi f s =
+ let l = length s in
+ if l = 0 then s else begin
+ let r = create l in
+ for i = 0 to l - 1 do unsafe_set r i (f i (unsafe_get s i)) done;
+ r
+ end
+
+let uppercase s = map Char.uppercase s
+let lowercase s = map Char.lowercase s
+
+let apply1 f s =
+ if length s = 0 then s else begin
+ let r = copy s in
+ unsafe_set r 0 (f(unsafe_get s 0));
+ r
+ end
+
+let capitalize s = apply1 Char.uppercase s
+let uncapitalize s = apply1 Char.lowercase s
+
+let rec index_rec s lim i c =
+ if i >= lim then raise Not_found else
+ if unsafe_get s i = c then i else index_rec s lim (i + 1) c;;
+
+let index s c = index_rec s (length s) 0 c;;
+
+let index_from s i c =
+ let l = length s in
+ if i < 0 || i > l then invalid_arg "Bytes.index_from" else
+ index_rec s l i c;;
+
+let rec rindex_rec s i c =
+ if i < 0 then raise Not_found else
+ if unsafe_get s i = c then i else rindex_rec s (i - 1) c;;
+
+let rindex s c = rindex_rec s (length s - 1) c;;
+
+let rindex_from s i c =
+ if i < -1 || i >= length s then invalid_arg "Bytes.rindex_from" else
+ rindex_rec s i c;;
+
+let contains_from s i c =
+ let l = length s in
+ if i < 0 || i > l then invalid_arg "Bytes.contains_from" else
+ try ignore (index_rec s l i c); true with Not_found -> false;;
+
+let contains s c = contains_from s 0 c;;
+
+let rcontains_from s i c =
+ if i < 0 || i >= length s then invalid_arg "Bytes.rcontains_from" else
+ try ignore (rindex_rec s i c); true with Not_found -> false;;
+
+type t = bytes
+
+let compare (x: t) (y: t) = Pervasives.compare x y
diff --git a/stdlib/bytes.mli b/stdlib/bytes.mli
new file mode 100644
index 0000000000..d9c1046740
--- /dev/null
+++ b/stdlib/bytes.mli
@@ -0,0 +1,238 @@
+(***********************************************************************)
+(* *)
+(* 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 Library General Public License, with *)
+(* the special exception on linking described in file ../LICENSE. *)
+(* *)
+(***********************************************************************)
+
+(** Byte sequence operations.
+
+ A byte sequence is a mutable data structure that contains a
+ fixed-length sequence of bytes. Each byte can be indexed in
+ constant time for reading or writing.
+
+ Given a byte sequence [s] of length [l], we can access each of the
+ [l] bytes of [s] via its index in the sequence. Indexes start at
+ [0], and we will call an index valid in [s] if it falls within the
+ range [[0...l-1]] (inclusive). A position is the point between two
+ bytes or at the beginning or end of the sequence. We call a
+ position valid in [s] if it falls within the range [[0...l]]
+ (inclusive). Note that the byte at index [n] is between positions
+ [n] and [n+1].
+
+ Two parameters [start] and [len] are said to designate a valid
+ range of [s] if [len >= 0] and [start] and [start+len] are valid
+ positions in [s].
+
+ Byte sequences can be modified in place, for instance via the [set]
+ and [blit] functions described below. See also strings (module
+ {!String}), which are almost the same data structure, but cannot be
+ modified in place.
+
+ Bytes are represented by the OCaml type [char].
+
+ @since 4.02.0
+ *)
+
+external length : bytes -> int = "%string_length"
+(** Return the length (number of bytes) of the argument. *)
+
+external get : bytes -> int -> char = "%string_safe_get"
+(** [get s n] returns the byte at index [n] in argument [s].
+
+ Raise [Invalid_argument] if [n] not a valid index in [s]. *)
+
+external set : bytes -> int -> char -> unit = "%string_safe_set"
+(** [set s n c] modifies [s] in place, replacing the byte at index [n]
+ with [c].
+
+ Raise [Invalid_argument] if [n] is not a valid index in [s]. *)
+
+external create : int -> bytes = "caml_create_string"
+(** [create n] returns a new byte sequence of length [n]. The
+ sequence is uninitialized and contains arbitrary bytes.
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
+
+val make : int -> char -> bytes
+(** [make n c] returns a new byte sequence of length [n], filled with
+ the byte [c].
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
+
+val init : int -> (int -> char) -> bytes
+(** [Bytes.init n f] returns a fresh byte sequence of length [n], with
+ character [i] initialized to the result of [f i] (in increasing
+ index order).
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
+
+val empty : bytes
+(** A byte sequence of size 0. *)
+
+val copy : bytes -> bytes
+(** Return a new byte sequence that contains the same bytes as the
+ argument. *)
+
+val of_string : string -> bytes
+(** Return a new byte sequence that contains the same bytes as the
+ given string. *)
+
+val to_string : bytes -> string
+(** Return a new string that contains the same bytes as the given byte
+ sequence. *)
+
+val sub : bytes -> int -> int -> bytes
+(** [sub s start len] returns a new byte sequence of length [len],
+ containing the subsequence of [s] that starts at position [start]
+ and has length [len].
+
+ Raise [Invalid_argument] if [start] and [len] do not designate a
+ valid range of [s]. *)
+
+val sub_string : bytes -> int -> int -> string
+(** Same as [sub] but return a string instead of a byte sequence. *)
+
+val fill : bytes -> int -> int -> char -> unit
+(** [fill s start len c] modifies [s] in place, replacing [len]
+ characters with [c], starting at [start].
+
+ Raise [Invalid_argument] if [start] and [len] do not designate a
+ valid range of [s]. *)
+
+val blit : bytes -> int -> bytes -> int -> int -> unit
+(** [blit src srcoff dst dstoff len] copies [len] bytes from sequence
+ [src], starting at index [srcoff], to sequence [dst], starting at
+ index [dstoff]. It works correctly even if [src] and [dst] are the
+ same byte sequence, and the source and destination intervals
+ overlap.
+
+ Raise [Invalid_argument] if [srcoff] and [len] do not
+ designate a valid range of [src], or if [dstoff] and [len]
+ do not designate a valid range of [dst]. *)
+
+val concat : bytes -> bytes list -> bytes
+(** [concat sep sl] concatenates the list of byte sequences [sl],
+ inserting the separator byte sequence [sep] between each, and
+ returns the result as a new byte sequence. *)
+
+val iter : (char -> unit) -> bytes -> unit
+(** [iter f s] applies function [f] in turn to all the bytes of [s].
+ It is equivalent to [f (get s 0); f (get s 1); ...; f (get s
+ (length s - 1)); ()]. *)
+
+val iteri : (int -> char -> unit) -> bytes -> unit
+(** Same as {!Bytes.iter}, but the function is applied to the index of
+ the byte as first argument and the byte itself as second
+ argument. *)
+
+val map : (char -> char) -> bytes -> bytes
+(** [map f s] applies function [f] in turn to all the bytes of [s]
+ (in increasing index order) and stores the resulting bytes in
+ a new sequence that is returned as the result. *)
+
+val mapi : (int -> char -> char) -> bytes -> bytes
+(** [mapi f s] calls [f] with each character of [s] and its
+ index (in increasing index order) and stores the resulting bytes
+ in a new sequence that is returned as the result. *)
+
+val trim : bytes -> bytes
+(** Return a copy of the argument, without leading and trailing
+ whitespace. The bytes regarded as whitespace are the ASCII
+ characters [' '], ['\012'], ['\n'], ['\r'], and ['\t']. *)
+
+val escaped : bytes -> bytes
+(** Return a copy of the argument, with special characters represented
+ by escape sequences, following the lexical conventions of OCaml. *)
+
+val index : bytes -> char -> int
+(** [index s c] returns the index of the first occurrence of byte [c]
+ in [s].
+
+ Raise [Not_found] if [c] does not occur in [s]. *)
+
+val rindex : bytes -> char -> int
+(** [rindex s c] returns the index of the last occurrence of byte [c]
+ in [s].
+
+ Raise [Not_found] if [c] does not occur in [s]. *)
+
+val index_from : bytes -> int -> char -> int
+(** [index_from s i c] returns the index of the first occurrence of
+ byte [c] in [s] after position [i]. [Bytes.index s c] is
+ equivalent to [Bytes.index_from s 0 c].
+
+ Raise [Invalid_argument] if [i] is not a valid position in [s].
+ Raise [Not_found] if [c] does not occur in [s] after position [i]. *)
+
+val rindex_from : bytes -> int -> char -> int
+(** [rindex_from s i c] returns the index of the last occurrence of
+ byte [c] in [s] before position [i+1]. [rindex s c] is equivalent
+ to [rindex_from s (Bytes.length s - 1) c].
+
+ Raise [Invalid_argument] if [i+1] is not a valid position in [s].
+ Raise [Not_found] if [c] does not occur in [s] before position [i+1]. *)
+
+val contains : bytes -> char -> bool
+(** [contains s c] tests if byte [c] appears in [s]. *)
+
+val contains_from : bytes -> int -> char -> bool
+(** [contains_from s start c] tests if byte [c] appears in [s] after
+ position [start]. [contains s c] is equivalent to [contains_from
+ s 0 c].
+
+ Raise [Invalid_argument] if [start] is not a valid position in [s]. *)
+
+val rcontains_from : bytes -> int -> char -> bool
+(** [rcontains_from s stop c] tests if byte [c] appears in [s] before
+ position [stop+1].
+
+ Raise [Invalid_argument] if [stop < 0] or [stop+1] is not a valid
+ position in [s]. *)
+
+val uppercase : bytes -> bytes
+(** Return a copy of the argument, with all lowercase letters
+ translated to uppercase, including accented letters of the ISO
+ Latin-1 (8859-1) character set. *)
+
+val lowercase : bytes -> bytes
+(** Return a copy of the argument, with all uppercase letters
+ translated to lowercase, including accented letters of the ISO
+ Latin-1 (8859-1) character set. *)
+
+val capitalize : bytes -> bytes
+(** Return a copy of the argument, with the first byte set to
+ uppercase. *)
+
+val uncapitalize : bytes -> bytes
+(** Return a copy of the argument, with the first byte set to
+ lowercase. *)
+
+type t = bytes
+(** An alias for the type of byte sequences. *)
+
+val compare: t -> t -> int
+(** The comparison function for byte sequences, with the same
+ specification as {!Pervasives.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}. *)
+
+(**/**)
+
+(* The following is for system use only. Do not call directly. *)
+
+external unsafe_get : bytes -> int -> char = "%string_unsafe_get"
+external unsafe_set : bytes -> int -> char -> unit = "%string_unsafe_set"
+external unsafe_blit :
+ bytes -> int -> bytes -> int -> int -> unit
+ = "caml_blit_string" "noalloc"
+external unsafe_fill :
+ bytes -> int -> int -> char -> unit = "caml_fill_string" "noalloc"
+external unsafe_to_string : bytes -> string = "%identity"
+external unsafe_of_string : string -> bytes = "%identity"
diff --git a/stdlib/bytesLabels.ml b/stdlib/bytesLabels.ml
new file mode 100644
index 0000000000..8ec8ec9e10
--- /dev/null
+++ b/stdlib/bytesLabels.ml
@@ -0,0 +1,16 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Jacques Garrigue, Kyoto University RIMS *)
+(* *)
+(* Copyright 2001 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the GNU Library General Public License, with *)
+(* the special exception on linking described in file ../LICENSE. *)
+(* *)
+(***********************************************************************)
+
+(* Module [BytesLabels]: labelled Bytes module *)
+
+include Bytes
diff --git a/stdlib/bytesLabels.mli b/stdlib/bytesLabels.mli
new file mode 100644
index 0000000000..23ccaf3911
--- /dev/null
+++ b/stdlib/bytesLabels.mli
@@ -0,0 +1,208 @@
+(***********************************************************************)
+(* *)
+(* 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 Library General Public License, with *)
+(* the special exception on linking described in file ../LICENSE. *)
+(* *)
+(***********************************************************************)
+
+(** Byte sequence operations. *)
+
+external length : bytes -> int = "%string_length"
+(** Return the length (number of bytes) of the argument. *)
+
+external get : bytes -> int -> char = "%string_safe_get"
+(** [get s n] returns the byte at index [n] in argument [s].
+
+ Raise [Invalid_argument] if [n] not a valid index in [s]. *)
+
+
+external set : bytes -> int -> char -> unit = "%string_safe_set"
+(** [set s n c] modifies [s] in place, replacing the byte at index [n]
+ with [c].
+
+ Raise [Invalid_argument] if [n] is not a valid index in [s]. *)
+
+external create : int -> bytes = "caml_create_string"
+(** [create n] returns a new byte sequence of length [n]. The
+ sequence is uninitialized and contains arbitrary bytes.
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
+
+val make : int -> char -> bytes
+(** [make n c] returns a new byte sequence of length [n], filled with
+ the byte [c].
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
+
+val init : int -> f:(int -> char) -> bytes
+(** [init n f] returns a fresh byte sequence of length [n],
+ with character [i] initialized to the result of [f i].
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
+
+val empty : bytes
+(** A byte sequence of size 0. *)
+
+val copy : bytes -> bytes
+(** Return a new byte sequence that contains the same bytes as the
+ argument. *)
+
+val of_string : string -> bytes
+(** Return a new byte sequence that contains the same bytes as the
+ given string. *)
+
+val to_string : bytes -> string
+(** Return a new string that contains the same bytes as the given byte
+ sequence. *)
+
+val sub : bytes -> pos:int -> len:int -> bytes
+(** [sub s start len] returns a new byte sequence of length [len],
+ containing the subsequence of [s] that starts at position [start]
+ and has length [len].
+
+ Raise [Invalid_argument] if [start] and [len] do not designate a
+ valid range of [s]. *)
+
+val sub_string : bytes -> int -> int -> string
+(** Same as [sub] but return a string instead of a byte sequence. *)
+
+val fill : bytes -> pos:int -> len:int -> char -> unit
+(** [fill s start len c] modifies [s] in place, replacing [len]
+ characters with [c], starting at [start].
+
+ Raise [Invalid_argument] if [start] and [len] do not designate a
+ valid range of [s]. *)
+
+val blit :
+ src:bytes -> src_pos:int -> dst:bytes -> dst_pos:int -> len:int
+ -> unit
+(** [blit src srcoff dst dstoff len] copies [len] bytes from sequence
+ [src], starting at index [srcoff], to sequence [dst], starting at
+ index [dstoff]. It works correctly even if [src] and [dst] are the
+ same byte sequence, and the source and destination intervals
+ overlap.
+
+ Raise [Invalid_argument] if [srcoff] and [len] do not
+ designate a valid range of [src], or if [dstoff] and [len]
+ do not designate a valid range of [dst]. *)
+
+val concat : sep:bytes -> bytes list -> bytes
+(** [concat sep sl] concatenates the list of byte sequences [sl],
+ inserting the separator byte sequence [sep] between each, and
+ returns the result as a new byte sequence. *)
+
+val iter : f:(char -> unit) -> bytes -> unit
+(** [iter f s] applies function [f] in turn to all the bytes of [s].
+ It is equivalent to [f (get s 0); f (get s 1); ...; f (get s
+ (length s - 1)); ()]. *)
+
+val iteri : f:(int -> char -> unit) -> bytes -> unit
+(** Same as {!Bytes.iter}, but the function is applied to the index of
+ the byte as first argument and the byte itself as second
+ argument. *)
+
+val map : f:(char -> char) -> bytes -> bytes
+(** [map f s] applies function [f] in turn to all the bytes of [s] and
+ stores the resulting bytes in a new sequence that is returned as
+ the result. *)
+
+val trim : bytes -> bytes
+(** Return a copy of the argument, without leading and trailing
+ whitespace. The bytes regarded as whitespace are the ASCII
+ characters [' '], ['\012'], ['\n'], ['\r'], and ['\t']. *)
+
+val escaped : bytes -> bytes
+(** Return a copy of the argument, with special characters represented
+ by escape sequences, following the lexical conventions of OCaml. *)
+
+val index : bytes -> char -> int
+(** [index s c] returns the index of the first occurrence of byte [c]
+ in [s].
+
+ Raise [Not_found] if [c] does not occur in [s]. *)
+
+val rindex : bytes -> char -> int
+(** [rindex s c] returns the index of the last occurrence of byte [c]
+ in [s].
+
+ Raise [Not_found] if [c] does not occur in [s]. *)
+
+val index_from : bytes -> int -> char -> int
+(** [index_from s i c] returns the index of the first occurrence of
+ byte [c] in [s] after position [i]. [Bytes.index s c] is
+ equivalent to [Bytes.index_from s 0 c].
+
+ Raise [Invalid_argument] if [i] is not a valid position in [s].
+ Raise [Not_found] if [c] does not occur in [s] after position [i]. *)
+
+val rindex_from : bytes -> int -> char -> int
+(** [rindex_from s i c] returns the index of the last occurrence of
+ byte [c] in [s] before position [i+1]. [rindex s c] is equivalent
+ to [rindex_from s (Bytes.length s - 1) c].
+
+ Raise [Invalid_argument] if [i+1] is not a valid position in [s].
+ Raise [Not_found] if [c] does not occur in [s] before position [i+1]. *)
+
+val contains : bytes -> char -> bool
+(** [contains s c] tests if byte [c] appears in [s]. *)
+
+val contains_from : bytes -> int -> char -> bool
+(** [contains_from s start c] tests if byte [c] appears in [s] after
+ position [start]. [contains s c] is equivalent to [contains_from
+ s 0 c].
+
+ Raise [Invalid_argument] if [start] is not a valid position in [s]. *)
+
+val rcontains_from : bytes -> int -> char -> bool
+(** [rcontains_from s stop c] tests if byte [c] appears in [s] before
+ position [stop+1].
+
+ Raise [Invalid_argument] if [stop < 0] or [stop+1] is not a valid
+ position in [s]. *)
+
+val uppercase : bytes -> bytes
+(** Return a copy of the argument, with all lowercase letters
+ translated to uppercase, including accented letters of the ISO
+ Latin-1 (8859-1) character set. *)
+
+val lowercase : bytes -> bytes
+(** Return a copy of the argument, with all uppercase letters
+ translated to lowercase, including accented letters of the ISO
+ Latin-1 (8859-1) character set. *)
+
+val capitalize : bytes -> bytes
+(** Return a copy of the argument, with the first byte set to
+ uppercase. *)
+
+val uncapitalize : bytes -> bytes
+(** Return a copy of the argument, with the first byte set to
+ lowercase. *)
+
+type t = bytes
+(** An alias for the type of byte sequences. *)
+
+val compare: t -> t -> int
+(** The comparison function for byte sequences, with the same
+ specification as {!Pervasives.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}. *)
+
+(**/**)
+
+(* The following is for system use only. Do not call directly. *)
+
+external unsafe_get : bytes -> int -> char = "%string_unsafe_get"
+external unsafe_set : bytes -> int -> char -> unit = "%string_unsafe_set"
+external unsafe_blit :
+ src:bytes -> src_pos:int -> dst:bytes -> dst_pos:int -> len:int ->
+ unit = "caml_blit_string" "noalloc"
+external unsafe_fill :
+ bytes -> pos:int -> len:int -> char -> unit = "caml_fill_string" "noalloc"
+external unsafe_to_string : bytes -> string = "%identity"
+external unsafe_of_string : string -> bytes = "%identity"
diff --git a/stdlib/camlinternalFormat.ml b/stdlib/camlinternalFormat.ml
new file mode 100644
index 0000000000..f28e05f180
--- /dev/null
+++ b/stdlib/camlinternalFormat.ml
@@ -0,0 +1,2610 @@
+open CamlinternalFormatBasics
+
+let legacy_behavior = true
+(** When this flag is enabled, the format parser tries to behave as
+ the <4.02 implementations, in particular it ignores most benine
+ nonsensical format. When the flag is disabled, it will reject any
+ format that is not accepted by the specification.
+
+ A typical example would be "%+ d": specifying both '+' (if the
+ number is positive, pad with a '+' to get the same width as
+ negative numbres) and ' ' (if the number is positive, pad with
+ a space) does not make sense, but the legacy (< 4.02)
+ implementation was happy to just ignore the space.
+*)
+
+
+(******************************************************************************)
+ (* Tools to manipulate scanning set of chars (see %[...]) *)
+
+type mutable_char_set = bytes
+
+(* Create a fresh, empty, mutable char set. *)
+let create_char_set () = Bytes.make 32 '\000'
+
+(* Add a char in a mutable char set. *)
+let add_in_char_set char_set c =
+ let ind = int_of_char c in
+ let str_ind = ind lsr 3 and mask = 1 lsl (ind land 0b111) in
+ Bytes.set char_set str_ind
+ (char_of_int (int_of_char (Bytes.get char_set str_ind) lor mask))
+
+let freeze_char_set char_set =
+ Bytes.to_string char_set
+
+(* Compute the complement of a char set. *)
+let rev_char_set char_set =
+ let char_set' = create_char_set () in
+ for i = 0 to 31 do
+ Bytes.set char_set' i
+ (char_of_int (int_of_char (String.get char_set i) lxor 0xFF));
+ done;
+ Bytes.unsafe_to_string char_set'
+
+(* Return true if a `c' is in `char_set'. *)
+let is_in_char_set char_set c =
+ let ind = int_of_char c in
+ let str_ind = ind lsr 3 and mask = 1 lsl (ind land 0b111) in
+ (int_of_char (String.get char_set str_ind) land mask) <> 0
+
+
+(******************************************************************************)
+ (* Ignored param conversion *)
+
+(* GADT used to abstract an existential type parameter. *)
+(* See param_format_of_ignored_format. *)
+type ('a, 'b, 'c, 'd, 'e, 'f) param_format_ebb = Param_format_EBB :
+ ('x -> 'a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) param_format_ebb
+
+(* Compute a padding associated to a pad_option (see "%_42d"). *)
+let pad_of_pad_opt pad_opt = match pad_opt with
+ | None -> No_padding
+ | Some width -> Lit_padding (Right, width)
+
+(* Compute a precision associated to a prec_option (see "%_.42f"). *)
+let prec_of_prec_opt prec_opt = match prec_opt with
+ | None -> No_precision
+ | Some ndec -> Lit_precision ndec
+
+(* Turn an ignored param into its equivalent not-ignored format node. *)
+(* Used for format pretty-printing and Scanf. *)
+let param_format_of_ignored_format : type a b c d e f x y .
+ (a, b, c, d, y, x) ignored -> (x, b, c, y, e, f) fmt ->
+ (a, b, c, d, e, f) param_format_ebb =
+fun ign fmt -> match ign with
+ | Ignored_char ->
+ Param_format_EBB (Char fmt)
+ | Ignored_caml_char ->
+ Param_format_EBB (Caml_char fmt)
+ | Ignored_string pad_opt ->
+ Param_format_EBB (String (pad_of_pad_opt pad_opt, fmt))
+ | Ignored_caml_string pad_opt ->
+ Param_format_EBB (Caml_string (pad_of_pad_opt pad_opt, fmt))
+ | Ignored_int (iconv, pad_opt) ->
+ Param_format_EBB (Int (iconv, pad_of_pad_opt pad_opt, No_precision, fmt))
+ | Ignored_int32 (iconv, pad_opt) ->
+ Param_format_EBB
+ (Int32 (iconv, pad_of_pad_opt pad_opt, No_precision, fmt))
+ | Ignored_nativeint (iconv, pad_opt) ->
+ Param_format_EBB
+ (Nativeint (iconv, pad_of_pad_opt pad_opt, No_precision, fmt))
+ | Ignored_int64 (iconv, pad_opt) ->
+ Param_format_EBB
+ (Int64 (iconv, pad_of_pad_opt pad_opt, No_precision, fmt))
+ | Ignored_float (pad_opt, prec_opt) ->
+ Param_format_EBB
+ (Float (Float_f, pad_of_pad_opt pad_opt, prec_of_prec_opt prec_opt, fmt))
+ | Ignored_bool ->
+ Param_format_EBB (Bool fmt)
+ | Ignored_format_arg (pad_opt, fmtty) ->
+ Param_format_EBB (Format_arg (pad_opt, fmtty, fmt))
+ | Ignored_format_subst (pad_opt, fmtty) ->
+ Param_format_EBB
+ (Format_subst (pad_opt, fmtty, fmt))
+ | Ignored_reader ->
+ Param_format_EBB (Reader fmt)
+ | Ignored_scan_char_set (width_opt, char_set) ->
+ Param_format_EBB (Scan_char_set (width_opt, char_set, fmt))
+ | Ignored_scan_get_counter counter ->
+ Param_format_EBB (Scan_get_counter (counter, fmt))
+
+
+(******************************************************************************)
+ (* Types *)
+
+type ('b, 'c) acc_formatting_gen =
+ | Acc_open_tag of ('b, 'c) acc
+ | Acc_open_box of ('b, 'c) acc
+
+(* Reversed list of printing atoms. *)
+(* Used to accumulate printf arguments. *)
+and ('b, 'c) acc =
+ | Acc_formatting_lit of ('b, 'c) acc * formatting_lit(* Special fmtting (box) *)
+ | Acc_formatting_gen of ('b, 'c) acc * ('b, 'c) acc_formatting_gen (* Special fmtting (box) *)
+ | Acc_string of ('b, 'c) acc * string (* Literal or generated string*)
+ | Acc_char of ('b, 'c) acc * char (* Literal or generated char *)
+ | Acc_delay of ('b, 'c) acc * ('b -> 'c) (* Delayed printing (%a, %t) *)
+ | Acc_flush of ('b, 'c) acc (* Flush *)
+ | Acc_invalid_arg of ('b, 'c) acc * string (* Raise Invalid_argument msg *)
+ | End_of_acc
+
+(* List of heterogeneous values. *)
+(* Used to accumulate scanf callback arguments. *)
+type ('a, 'b) heter_list =
+ | Cons : 'c * ('a, 'b) heter_list -> ('c -> 'a, 'b) heter_list
+ | Nil : ('b, 'b) heter_list
+
+(* Existential Black Boxes. *)
+(* Used to abstract some existential type parameters. *)
+
+(* GADT type associating a padding and an fmtty. *)
+(* See the type_padding function. *)
+type ('a, 'b, 'c, 'd, 'e, 'f) padding_fmtty_ebb = Padding_fmtty_EBB :
+ ('x, 'y) padding * ('y, 'b, 'c, 'd, 'e, 'f) fmtty ->
+ ('x, 'b, 'c, 'd, 'e, 'f) padding_fmtty_ebb
+
+(* GADT type associating a padding, a precision and an fmtty. *)
+(* See the type_padprec function. *)
+type ('a, 'b, 'c, 'd, 'e, 'f) padprec_fmtty_ebb = Padprec_fmtty_EBB :
+ ('x, 'y) padding * ('y, 'z) precision * ('z, 'b, 'c, 'd, 'e, 'f) fmtty ->
+ ('x, 'b, 'c, 'd, 'e, 'f) padprec_fmtty_ebb
+
+(* GADT type associating a padding and an fmt. *)
+(* See make_padding_fmt_ebb and parse_format functions. *)
+type ('a, 'b, 'c, 'e, 'f) padding_fmt_ebb = Padding_fmt_EBB :
+ (_, 'x -> 'a) padding *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'e, 'f) padding_fmt_ebb
+
+(* GADT type associating a precision and an fmt. *)
+(* See make_precision_fmt_ebb and parse_format functions. *)
+type ('a, 'b, 'c, 'e, 'f) precision_fmt_ebb = Precision_fmt_EBB :
+ (_, 'x -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'e, 'f) precision_fmt_ebb
+
+(* GADT type associating a padding, a precision and an fmt. *)
+(* See make_padprec_fmt_ebb and parse_format functions. *)
+type ('p, 'b, 'c, 'e, 'f) padprec_fmt_ebb = Padprec_fmt_EBB :
+ ('x, 'y) padding * ('y, 'p -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('p, 'b, 'c, 'e, 'f) padprec_fmt_ebb
+
+(* Abstract the 'a and 'd parameters of an fmt. *)
+(* Output type of the format parsing function. *)
+type ('b, 'c, 'e, 'f) fmt_ebb = Fmt_EBB :
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('b, 'c, 'e, 'f) fmt_ebb
+
+(* GADT type associating an fmtty and an fmt. *)
+(* See the type_format_gen function. *)
+type ('a, 'b, 'c, 'd, 'e, 'f) fmt_fmtty_ebb = Fmt_fmtty_EBB :
+ ('a, 'b, 'c, 'd, 'y, 'x) fmt *
+ ('x, 'b, 'c, 'y, 'e, 'f) fmtty ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt_fmtty_ebb
+
+(* GADT type associating an fmtty and an fmt. *)
+(* See the type_ignored_format_substitution function. *)
+type ('a, 'b, 'c, 'd, 'e, 'f) fmtty_fmt_ebb = Fmtty_fmt_EBB :
+ ('a, 'b, 'c, 'd, 'y, 'x) fmtty *
+ ('x, 'b, 'c, 'y, 'e, 'f) fmt_fmtty_ebb ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmtty_fmt_ebb
+
+(* Abstract all fmtty type parameters. *)
+(* Used to compare format types. *)
+type fmtty_ebb = Fmtty_EBB : ('a, 'b, 'c, 'd, 'e, 'f) fmtty -> fmtty_ebb
+
+(* Abstract all padding type parameters. *)
+(* Used to compare paddings. *)
+type padding_ebb = Padding_EBB : ('a, 'b) padding -> padding_ebb
+
+(* Abstract all precision type parameters. *)
+(* Used to compare precisions. *)
+type precision_ebb = Precision_EBB : ('a, 'b) precision -> precision_ebb
+
+(******************************************************************************)
+ (* Constants *)
+
+(* Default precision for float printing. *)
+let default_float_precision = 6
+
+(******************************************************************************)
+ (* Externals *)
+
+external format_float: string -> float -> string
+ = "caml_format_float"
+external format_int: string -> int -> string
+ = "caml_format_int"
+external format_int32: string -> int32 -> string
+ = "caml_int32_format"
+external format_nativeint: string -> nativeint -> string
+ = "caml_nativeint_format"
+external format_int64: string -> int64 -> string
+ = "caml_int64_format"
+
+(******************************************************************************)
+ (* Tools to pretty-print formats *)
+
+(* Type of extensible character buffers. *)
+type buffer = {
+ mutable ind : int;
+ mutable bytes : bytes;
+}
+
+(* Create a fresh buffer. *)
+let buffer_create init_size = { ind = 0; bytes = Bytes.create init_size }
+
+(* Check size of the buffer and grow it if needed. *)
+let buffer_check_size buf overhead =
+ let len = Bytes.length buf.bytes in
+ let min_len = buf.ind + overhead in
+ if min_len > len then (
+ let new_len = max (len * 2) min_len in
+ let new_str = Bytes.create new_len in
+ Bytes.blit buf.bytes 0 new_str 0 len;
+ buf.bytes <- new_str;
+ )
+
+(* Add the character `c' to the buffer `buf'. *)
+let buffer_add_char buf c =
+ buffer_check_size buf 1;
+ Bytes.set buf.bytes buf.ind c;
+ buf.ind <- buf.ind + 1
+
+(* Add the string `s' to the buffer `buf'. *)
+let buffer_add_string buf s =
+ let str_len = String.length s in
+ buffer_check_size buf str_len;
+ String.blit s 0 buf.bytes buf.ind str_len;
+ buf.ind <- buf.ind + str_len
+
+(* Get the content of the buffer. *)
+let buffer_contents buf =
+ Bytes.sub_string buf.bytes 0 buf.ind
+
+(***)
+
+(* 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'
+
+(* Convert a float conversion to char. *)
+let char_of_fconv fconv = match fconv with
+ | Float_f | Float_pf | Float_sf -> 'f' | Float_e | Float_pe | Float_se -> 'e'
+ | Float_E | Float_pE | Float_sE -> 'E' | Float_g | Float_pg | Float_sg -> 'g'
+ | Float_G | Float_pG | Float_sG -> 'G' | Float_F -> 'F'
+
+(* Convert a scanning counter to char. *)
+let char_of_counter counter = match counter with
+ | Line_counter -> 'l'
+ | Char_counter -> 'n'
+ | Token_counter -> 'N'
+
+(***)
+
+(* Print a char_set in a buffer with the OCaml format lexical convention. *)
+let bprint_char_set buf char_set =
+ let rec print_start set =
+ let is_alone c =
+ let before, after = Char.(chr (code c - 1), chr (code c + 1)) in
+ is_in_char_set set c
+ && not (is_in_char_set set before && is_in_char_set set after) in
+ if is_alone ']' then buffer_add_char buf ']';
+ print_out set 1;
+ if is_alone '-' then buffer_add_char buf '-';
+ and print_out set i =
+ if i < 256 then
+ if is_in_char_set set (char_of_int i) then print_first set i
+ else print_out set (i + 1)
+ and print_first set i =
+ match char_of_int i with
+ | '\255' -> print_char buf 255;
+ | ']' | '-' -> print_out set (i + 1);
+ | _ -> print_second set (i + 1);
+ and print_second set i =
+ if is_in_char_set set (char_of_int i) then
+ match char_of_int i with
+ | '\255' ->
+ print_char buf 254;
+ print_char buf 255;
+ | ']' | '-' when not (is_in_char_set set (char_of_int (i + 1))) ->
+ print_char buf (i - 1);
+ print_out set (i + 1);
+ | _ when not (is_in_char_set set (char_of_int (i + 1))) ->
+ print_char buf (i - 1);
+ print_char buf i;
+ print_out set (i + 2);
+ | _ ->
+ print_in set (i - 1) (i + 2);
+ else (
+ print_char buf (i - 1);
+ print_out set (i + 1);
+ )
+ and print_in set i j =
+ if j = 256 || not (is_in_char_set set (char_of_int j)) then (
+ print_char buf i;
+ print_char buf (int_of_char '-');
+ print_char buf (j - 1);
+ if j < 256 then print_out set (j + 1);
+ ) else
+ print_in set i (j + 1);
+ and print_char buf i = match char_of_int i with
+ | '%' -> buffer_add_char buf '%'; buffer_add_char buf '%';
+ | '@' -> buffer_add_char buf '%'; buffer_add_char buf '@';
+ | c -> buffer_add_char buf c;
+ in
+ buffer_add_char buf '[';
+ print_start (
+ if is_in_char_set char_set '\000'
+ then ( buffer_add_char buf '^'; rev_char_set char_set )
+ else char_set
+ );
+ buffer_add_char buf ']'
+
+(***)
+
+(* Print a padty in a buffer with the format-like syntax. *)
+let bprint_padty buf padty = match padty with
+ | Left -> buffer_add_char buf '-'
+ | Right -> ()
+ | Zeros -> buffer_add_char buf '0'
+
+(* Print the '_' of an ignored flag if needed. *)
+let bprint_ignored_flag buf ign_flag =
+ if ign_flag then buffer_add_char buf '_'
+
+(***)
+
+let bprint_pad_opt buf pad_opt = match pad_opt with
+ | None -> ()
+ | Some width -> buffer_add_string buf (string_of_int width)
+
+(***)
+
+(* Print padding in a buffer with the format-like syntax. *)
+let bprint_padding : type a b . buffer -> (a, b) padding -> unit =
+fun buf pad -> match pad with
+ | No_padding -> ()
+ | Lit_padding (padty, n) ->
+ bprint_padty buf padty;
+ buffer_add_string buf (string_of_int n);
+ | Arg_padding padty ->
+ bprint_padty buf padty;
+ buffer_add_char buf '*'
+
+(* Print precision in a buffer with the format-like syntax. *)
+let bprint_precision : type a b . buffer -> (a, b) precision -> unit =
+ fun buf prec -> match prec with
+ | No_precision -> ()
+ | Lit_precision n ->
+ buffer_add_char buf '.';
+ buffer_add_string buf (string_of_int n);
+ | Arg_precision ->
+ buffer_add_string buf ".*"
+
+(***)
+
+(* Print the optionnal '+', ' ' or '#' associated to an int conversion. *)
+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_d | Int_i | Int_x | Int_X | Int_o | Int_u -> ()
+
+(* Print an complete int format in a buffer (ex: "%3.*d"). *)
+let bprint_int_fmt buf ign_flag iconv pad prec =
+ buffer_add_char buf '%';
+ bprint_ignored_flag buf ign_flag;
+ bprint_iconv_flag buf iconv;
+ bprint_padding buf pad;
+ bprint_precision buf prec;
+ buffer_add_char buf (char_of_iconv iconv)
+
+(* Print a complete int32, nativeint or int64 format in a buffer. *)
+let bprint_altint_fmt buf ign_flag iconv pad prec c =
+ buffer_add_char buf '%';
+ bprint_ignored_flag buf ign_flag;
+ bprint_iconv_flag buf iconv;
+ bprint_padding buf pad;
+ bprint_precision buf prec;
+ buffer_add_char buf c;
+ buffer_add_char buf (char_of_iconv iconv)
+
+(***)
+
+(* Print the optionnal '+' associated to a float conversion. *)
+let bprint_fconv_flag buf fconv = match fconv with
+ | Float_pf | Float_pe | Float_pE | Float_pg | Float_pG ->
+ buffer_add_char buf '+'
+ | Float_sf | Float_se | Float_sE | Float_sg | Float_sG ->
+ buffer_add_char buf ' '
+ | Float_f | Float_e | Float_E | Float_g | Float_G | Float_F ->
+ ()
+
+(* Print a complete float format in a buffer (ex: "%+*.3f"). *)
+let bprint_float_fmt buf ign_flag fconv pad prec =
+ buffer_add_char buf '%';
+ bprint_ignored_flag buf ign_flag;
+ bprint_fconv_flag buf fconv;
+ bprint_padding buf pad;
+ bprint_precision buf prec;
+ buffer_add_char buf (char_of_fconv fconv)
+
+(* Compute the literal string representation of a formatting_lit. *)
+(* Also used by Printf and Scanf where formatting is not interpreted. *)
+let string_of_formatting_lit formatting_lit = match formatting_lit with
+ | Close_box -> "@]"
+ | Close_tag -> "@}"
+ | Break (str, _, _) -> str
+ | FFlush -> "@?"
+ | Force_newline -> "@\n"
+ | Flush_newline -> "@."
+ | Magic_size (str, _) -> str
+ | Escaped_at -> "@@"
+ | Escaped_percent -> "@%"
+ | Scan_indic c -> "@" ^ (String.make 1 c)
+
+(* Compute the literal string representation of a formatting. *)
+(* Also used by Printf and Scanf where formatting is not interpreted. *)
+let string_of_formatting_gen : type a b c d e f .
+ (a, b, c, d, e, f) formatting_gen -> string =
+ fun formatting_gen -> match formatting_gen with
+ | Open_tag (Format (_, str)) -> str
+ | Open_box (Format (_, str)) -> str
+
+(***)
+
+(* Print a literal char in a buffer, escape '%' by "%%". *)
+let bprint_char_literal buf chr = match chr with
+ | '%' -> buffer_add_string buf "%%"
+ | _ -> buffer_add_char buf chr
+
+(* Print a literal string in a buffer, escape all '%' by "%%". *)
+let bprint_string_literal buf str =
+ for i = 0 to String.length str - 1 do
+ bprint_char_literal buf str.[i]
+ done
+
+(******************************************************************************)
+ (* Format pretty-printing *)
+
+(* Print a complete format type (an fmtty) in a buffer. *)
+let rec bprint_fmtty : type a b c d e f g h i j k l .
+ buffer -> (a, b, c, d, e, f, g, h, i, j, k, l) fmtty_rel -> unit =
+fun buf fmtty -> match fmtty with
+ | Char_ty rest -> buffer_add_string buf "%c"; bprint_fmtty buf rest;
+ | String_ty rest -> buffer_add_string buf "%s"; bprint_fmtty buf rest;
+ | Int_ty rest -> buffer_add_string buf "%i"; bprint_fmtty buf rest;
+ | Int32_ty rest -> buffer_add_string buf "%li"; bprint_fmtty buf rest;
+ | Nativeint_ty rest -> buffer_add_string buf "%ni"; bprint_fmtty buf rest;
+ | Int64_ty rest -> buffer_add_string buf "%Li"; bprint_fmtty buf rest;
+ | Float_ty rest -> buffer_add_string buf "%f"; bprint_fmtty buf rest;
+ | Bool_ty rest -> buffer_add_string buf "%B"; bprint_fmtty buf rest;
+ | Alpha_ty rest -> buffer_add_string buf "%a"; bprint_fmtty buf rest;
+ | Theta_ty rest -> buffer_add_string buf "%t"; bprint_fmtty buf rest;
+ | Reader_ty rest -> buffer_add_string buf "%r"; bprint_fmtty buf rest;
+
+ | Ignored_reader_ty rest ->
+ buffer_add_string buf "%_r";
+ bprint_fmtty buf rest;
+
+ | Format_arg_ty (sub_fmtty, rest) ->
+ buffer_add_string buf "%{"; bprint_fmtty buf sub_fmtty;
+ buffer_add_string buf "%}"; bprint_fmtty buf rest;
+ | Format_subst_ty (sub_fmtty, _, rest) ->
+ buffer_add_string buf "%("; bprint_fmtty buf sub_fmtty;
+ buffer_add_string buf "%)"; bprint_fmtty buf rest;
+
+ | End_of_fmtty -> ()
+
+(***)
+
+(* Print a complete format in a buffer. *)
+let bprint_fmt buf fmt =
+ let rec fmtiter : type a b c d e f .
+ (a, b, c, d, e, f) fmt -> bool -> unit =
+ fun fmt ign_flag -> match fmt with
+ | String (pad, rest) ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ bprint_padding buf pad; buffer_add_char buf 's';
+ fmtiter rest false;
+ | Caml_string (pad, rest) ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ bprint_padding buf pad; buffer_add_char buf 'S';
+ fmtiter rest false;
+
+ | Int (iconv, pad, prec, rest) ->
+ bprint_int_fmt buf ign_flag iconv pad prec;
+ fmtiter rest false;
+ | Int32 (iconv, pad, prec, rest) ->
+ bprint_altint_fmt buf ign_flag iconv pad prec 'l';
+ fmtiter rest false;
+ | Nativeint (iconv, pad, prec, rest) ->
+ bprint_altint_fmt buf ign_flag iconv pad prec 'n';
+ fmtiter rest false;
+ | Int64 (iconv, pad, prec, rest) ->
+ bprint_altint_fmt buf ign_flag iconv pad prec 'L';
+ fmtiter rest false;
+ | Float (fconv, pad, prec, rest) ->
+ bprint_float_fmt buf ign_flag fconv pad prec;
+ fmtiter rest false;
+
+ | Char rest ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ buffer_add_char buf 'c'; fmtiter rest false;
+ | Caml_char rest ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ buffer_add_char buf 'C'; fmtiter rest false;
+ | Bool rest ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ buffer_add_char buf 'B'; fmtiter rest false;
+ | Alpha rest ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ buffer_add_char buf 'a'; fmtiter rest false;
+ | Theta rest ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ buffer_add_char buf 't'; fmtiter rest false;
+ | Reader rest ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ buffer_add_char buf 'r'; fmtiter rest false;
+ | Flush rest ->
+ buffer_add_string buf "%!";
+ fmtiter rest ign_flag;
+
+ | String_literal (str, rest) ->
+ bprint_string_literal buf str;
+ fmtiter rest ign_flag;
+ | Char_literal (chr, rest) ->
+ bprint_char_literal buf chr;
+ fmtiter rest ign_flag;
+
+ | Format_arg (pad_opt, fmtty, rest) ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ bprint_pad_opt buf pad_opt; buffer_add_char buf '{';
+ bprint_fmtty buf fmtty; buffer_add_char buf '%'; buffer_add_char buf '}';
+ fmtiter rest false;
+ | Format_subst (pad_opt, fmtty, rest) ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ bprint_pad_opt buf pad_opt; buffer_add_char buf '(';
+ bprint_fmtty buf fmtty; buffer_add_char buf '%'; buffer_add_char buf ')';
+ fmtiter rest false;
+
+ | Scan_char_set (width_opt, char_set, rest) ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ bprint_pad_opt buf width_opt; bprint_char_set buf char_set;
+ fmtiter rest false;
+ | Scan_get_counter (counter, rest) ->
+ buffer_add_char buf '%'; bprint_ignored_flag buf ign_flag;
+ buffer_add_char buf (char_of_counter counter);
+ fmtiter rest false;
+ | Ignored_param (ign, rest) ->
+ let Param_format_EBB fmt' = param_format_of_ignored_format ign rest in
+ fmtiter fmt' true;
+
+ | Formatting_lit (fmting_lit, rest) ->
+ bprint_string_literal buf (string_of_formatting_lit fmting_lit);
+ fmtiter rest ign_flag;
+ | Formatting_gen (fmting_gen, rest) ->
+ bprint_string_literal buf "@{";
+ bprint_string_literal buf (string_of_formatting_gen fmting_gen);
+ fmtiter rest ign_flag;
+
+ | End_of_format -> ()
+
+ in fmtiter fmt false
+
+(***)
+
+(* Convert a format to string. *)
+let string_of_fmt fmt =
+ let buf = buffer_create 16 in
+ bprint_fmt buf fmt;
+ buffer_contents buf
+
+(******************************************************************************)
+ (* Type extraction *)
+
+type (_, _) eq = Refl : ('a, 'a) eq
+
+(* Invariant: this function is the identity on values.
+
+ In particular, if (ty1, ty2) have equal values, then
+ (trans (symm ty1) ty2) respects the 'trans' precondition. *)
+let rec symm : type a1 b1 c1 d1 e1 f1 a2 b2 c2 d2 e2 f2 .
+ (a1, b1, c1, d1, e1, f1,
+ a2, b2, c2, d2, e2, f2) fmtty_rel
+-> (a2, b2, c2, d2, e2, f2,
+ a1, b1, c1, d1, e1, f1) fmtty_rel
+= function
+ | Char_ty rest -> Char_ty (symm rest)
+ | Int_ty rest -> Int_ty (symm rest)
+ | Int32_ty rest -> Int32_ty (symm rest)
+ | Int64_ty rest -> Int64_ty (symm rest)
+ | Nativeint_ty rest -> Nativeint_ty (symm rest)
+ | Float_ty rest -> Float_ty (symm rest)
+ | Bool_ty rest -> Bool_ty (symm rest)
+ | String_ty rest -> String_ty (symm rest)
+ | Theta_ty rest -> Theta_ty (symm rest)
+ | Alpha_ty rest -> Alpha_ty (symm rest)
+ | Reader_ty rest -> Reader_ty (symm rest)
+ | Ignored_reader_ty rest -> Ignored_reader_ty (symm rest)
+ | Format_arg_ty (ty, rest) ->
+ Format_arg_ty (ty, symm rest)
+ | Format_subst_ty (ty1, ty2, rest) ->
+ Format_subst_ty (ty2, ty1, symm rest)
+ | End_of_fmtty -> End_of_fmtty
+
+let rec fmtty_rel_det : type a1 b c d1 e1 f1 a2 d2 e2 f2 .
+ (a1, b, c, d1, e1, f1,
+ a2, b, c, d2, e2, f2) fmtty_rel ->
+ ((f1, f2) eq -> (a1, a2) eq)
+ * ((a1, a2) eq -> (f1, f2) eq)
+ * ((e1, e2) eq -> (d1, d2) eq)
+ * ((d1, d2) eq -> (e1, e2) eq)
+= function
+ | End_of_fmtty ->
+ (fun Refl -> Refl),
+ (fun Refl -> Refl),
+ (fun Refl -> Refl),
+ (fun Refl -> Refl)
+ | Char_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | String_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | Int_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | Int32_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | Int64_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | Nativeint_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | Float_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | Bool_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+
+ | Theta_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | Alpha_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | Reader_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ (fun Refl -> let Refl = ed Refl in Refl),
+ (fun Refl -> let Refl = de Refl in Refl)
+ | Ignored_reader_ty rest ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ (fun Refl -> let Refl = ed Refl in Refl),
+ (fun Refl -> let Refl = de Refl in Refl)
+ | Format_arg_ty (_ty, rest) ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ (fun Refl -> let Refl = fa Refl in Refl),
+ (fun Refl -> let Refl = af Refl in Refl),
+ ed, de
+ | Format_subst_ty (ty1, ty2, rest) ->
+ let fa, af, ed, de = fmtty_rel_det rest in
+ let ty = trans (symm ty1) ty2 in
+ let ag, ga, dj, jd = fmtty_rel_det ty in
+ (fun Refl -> let Refl = fa Refl in let Refl = ag Refl in Refl),
+ (fun Refl -> let Refl = ga Refl in let Refl = af Refl in Refl),
+ (fun Refl -> let Refl = ed Refl in let Refl = dj Refl in Refl),
+ (fun Refl -> let Refl = jd Refl in let Refl = de Refl in Refl)
+
+(* Precondition: we assume that the two fmtty_rel arguments have equal
+ values (at possibly distinct types); this invariant comes from the way
+ fmtty_rel witnesses are produced by the type-checker
+
+ The code below uses (assert false) when this assumption is broken. The
+ code pattern is the following:
+
+ | Foo x, Foo y ->
+ (* case where indeed both values
+ start with constructor Foo *)
+ | Foo _, _
+ | _, Foo _ ->
+ (* different head constructors: broken precondition *)
+ assert false
+*)
+and trans : type
+ a1 b1 c1 d1 e1 f1
+ a2 b2 c2 d2 e2 f2
+ a3 b3 c3 d3 e3 f3
+.
+ (a1, b1, c1, d1, e1, f1,
+ a2, b2, c2, d2, e2, f2) fmtty_rel
+-> (a2, b2, c2, d2, e2, f2,
+ a3, b3, c3, d3, e3, f3) fmtty_rel
+-> (a1, b1, c1, d1, e1, f1,
+ a3, b3, c3, d3, e3, f3) fmtty_rel
+= fun ty1 ty2 -> match ty1, ty2 with
+ | Char_ty rest1, Char_ty rest2 -> Char_ty (trans rest1 rest2)
+ | String_ty rest1, String_ty rest2 -> String_ty (trans rest1 rest2)
+ | Bool_ty rest1, Bool_ty rest2 -> Bool_ty (trans rest1 rest2)
+ | Int_ty rest1, Int_ty rest2 -> Int_ty (trans rest1 rest2)
+ | Int32_ty rest1, Int32_ty rest2 -> Int32_ty (trans rest1 rest2)
+ | Int64_ty rest1, Int64_ty rest2 -> Int64_ty (trans rest1 rest2)
+ | Nativeint_ty rest1, Nativeint_ty rest2 -> Nativeint_ty (trans rest1 rest2)
+ | Float_ty rest1, Float_ty rest2 -> Float_ty (trans rest1 rest2)
+
+ | Alpha_ty rest1, Alpha_ty rest2 -> Alpha_ty (trans rest1 rest2)
+ | Alpha_ty _, _ -> assert false
+ | _, Alpha_ty _ -> assert false
+
+ | Theta_ty rest1, Theta_ty rest2 -> Theta_ty (trans rest1 rest2)
+ | Theta_ty _, _ -> assert false
+ | _, Theta_ty _ -> assert false
+
+ | Reader_ty rest1, Reader_ty rest2 -> Reader_ty (trans rest1 rest2)
+ | Reader_ty _, _ -> assert false
+ | _, Reader_ty _ -> assert false
+
+ | Ignored_reader_ty rest1, Ignored_reader_ty rest2 ->
+ Ignored_reader_ty (trans rest1 rest2)
+ | Ignored_reader_ty _, _ -> assert false
+ | _, Ignored_reader_ty _ -> assert false
+
+ | Format_arg_ty (ty1, rest1), Format_arg_ty (ty2, rest2) ->
+ Format_arg_ty (trans ty1 ty2, trans rest1 rest2)
+ | Format_arg_ty _, _ -> assert false
+ | _, Format_arg_ty _ -> assert false
+
+ | Format_subst_ty (ty11, ty12, rest1),
+ Format_subst_ty (ty21, ty22, rest2) ->
+ let ty = trans (symm ty12) ty21 in
+ let _, f2, _, f4 = fmtty_rel_det ty in
+ let Refl = f2 Refl in
+ let Refl = f4 Refl in
+ Format_subst_ty (ty11, ty22, trans rest1 rest2)
+ | Format_subst_ty _, _ -> assert false
+ | _, Format_subst_ty _ -> assert false
+
+ | End_of_fmtty, End_of_fmtty -> End_of_fmtty
+ | End_of_fmtty, _ -> assert false
+ | _, End_of_fmtty -> assert false
+
+let rec fmtty_of_formatting_gen : type a b c d e f .
+ (a, b, c, d, e, f) formatting_gen ->
+ (a, b, c, d, e, f) fmtty =
+fun formatting_gen -> match formatting_gen with
+ | Open_tag (Format (fmt, _)) -> fmtty_of_fmt fmt
+ | Open_box (Format (fmt, _)) -> fmtty_of_fmt fmt
+
+(* Extract the type representation (an fmtty) of a format. *)
+and fmtty_of_fmt : type a b c d e f .
+ (a, b, c, d, e, f) fmt -> (a, b, c, d, e, f) fmtty =
+fun fmtty -> match fmtty with
+ | String (pad, rest) ->
+ fmtty_of_padding_fmtty pad (String_ty (fmtty_of_fmt rest))
+ | Caml_string (pad, rest) ->
+ fmtty_of_padding_fmtty pad (String_ty (fmtty_of_fmt rest))
+
+ | Int (_, pad, prec, rest) ->
+ let ty_rest = fmtty_of_fmt rest in
+ let prec_ty = fmtty_of_precision_fmtty prec (Int_ty ty_rest) in
+ fmtty_of_padding_fmtty pad prec_ty
+ | Int32 (_, pad, prec, rest) ->
+ let ty_rest = fmtty_of_fmt rest in
+ let prec_ty = fmtty_of_precision_fmtty prec (Int32_ty ty_rest) in
+ fmtty_of_padding_fmtty pad prec_ty
+ | Nativeint (_, pad, prec, rest) ->
+ let ty_rest = fmtty_of_fmt rest in
+ let prec_ty = fmtty_of_precision_fmtty prec (Nativeint_ty ty_rest) in
+ fmtty_of_padding_fmtty pad prec_ty
+ | Int64 (_, pad, prec, rest) ->
+ let ty_rest = fmtty_of_fmt rest in
+ let prec_ty = fmtty_of_precision_fmtty prec (Int64_ty ty_rest) in
+ fmtty_of_padding_fmtty pad prec_ty
+ | Float (_, pad, prec, rest) ->
+ let ty_rest = fmtty_of_fmt rest in
+ let prec_ty = fmtty_of_precision_fmtty prec (Float_ty ty_rest) in
+ fmtty_of_padding_fmtty pad prec_ty
+
+ | Char rest -> Char_ty (fmtty_of_fmt rest)
+ | Caml_char rest -> Char_ty (fmtty_of_fmt rest)
+ | Bool rest -> Bool_ty (fmtty_of_fmt rest)
+ | Alpha rest -> Alpha_ty (fmtty_of_fmt rest)
+ | Theta rest -> Theta_ty (fmtty_of_fmt rest)
+ | Reader rest -> Reader_ty (fmtty_of_fmt rest)
+
+ | Format_arg (_, ty, rest) ->
+ Format_arg_ty (ty, fmtty_of_fmt rest)
+ | Format_subst (_, ty, rest) ->
+ Format_subst_ty (ty, ty, fmtty_of_fmt rest)
+
+ | Flush rest -> fmtty_of_fmt rest
+ | String_literal (_, rest) -> fmtty_of_fmt rest
+ | Char_literal (_, rest) -> fmtty_of_fmt rest
+
+ | Scan_char_set (_, _, rest) -> String_ty (fmtty_of_fmt rest)
+ | Scan_get_counter (_, rest) -> Int_ty (fmtty_of_fmt rest)
+ | Ignored_param (ign, rest) -> fmtty_of_ignored_format ign rest
+ | Formatting_lit (_, rest) -> fmtty_of_fmt rest
+ | Formatting_gen (fmting_gen, rest) ->
+ concat_fmtty (fmtty_of_formatting_gen fmting_gen) (fmtty_of_fmt rest)
+
+ | End_of_format -> End_of_fmtty
+
+(* Extract the fmtty of an ignored parameter followed by the rest of
+ the format. *)
+and fmtty_of_ignored_format : type x y a b c d e f .
+ (a, b, c, d, y, x) ignored ->
+ (x, b, c, y, e, f) fmt ->
+ (a, b, c, d, e, f) fmtty =
+fun ign fmt -> match ign with
+ | Ignored_char -> fmtty_of_fmt fmt
+ | Ignored_caml_char -> fmtty_of_fmt fmt
+ | Ignored_string _ -> fmtty_of_fmt fmt
+ | Ignored_caml_string _ -> fmtty_of_fmt fmt
+ | Ignored_int (_, _) -> fmtty_of_fmt fmt
+ | Ignored_int32 (_, _) -> fmtty_of_fmt fmt
+ | Ignored_nativeint (_, _) -> fmtty_of_fmt fmt
+ | Ignored_int64 (_, _) -> fmtty_of_fmt fmt
+ | Ignored_float (_, _) -> fmtty_of_fmt fmt
+ | Ignored_bool -> fmtty_of_fmt fmt
+ | Ignored_format_arg _ -> fmtty_of_fmt fmt
+ | Ignored_format_subst (_, fmtty) -> concat_fmtty fmtty (fmtty_of_fmt fmt)
+ | Ignored_reader -> Ignored_reader_ty (fmtty_of_fmt fmt)
+ | Ignored_scan_char_set _ -> fmtty_of_fmt fmt
+ | Ignored_scan_get_counter _ -> fmtty_of_fmt fmt
+
+(* Add an Int_ty node if padding is taken as an extra argument (ex: "%*s"). *)
+and fmtty_of_padding_fmtty : type x a b c d e f .
+ (x, a) padding -> (a, b, c, d, e, f) fmtty -> (x, b, c, d, e, f) fmtty =
+ fun pad fmtty -> match pad with
+ | No_padding -> fmtty
+ | Lit_padding _ -> fmtty
+ | Arg_padding _ -> Int_ty fmtty
+
+(* Add an Int_ty node if precision is taken as an extra argument (ex: "%.*f").*)
+and fmtty_of_precision_fmtty : type x a b c d e f .
+ (x, a) precision -> (a, b, c, d, e, f) fmtty -> (x, b, c, d, e, f) fmtty =
+ fun prec fmtty -> match prec with
+ | No_precision -> fmtty
+ | Lit_precision _ -> fmtty
+ | Arg_precision -> Int_ty fmtty
+
+(******************************************************************************)
+ (* Format typing *)
+
+(* Exception raised when a format does not match a given format type. *)
+exception Type_mismatch
+
+(* Type a padding. *)
+(* Take an Int_ty from the fmtty if the integer should be kept as argument. *)
+(* Raise Type_mismatch in case of type mismatch. *)
+let type_padding : type a b c d e f x y .
+ (x, y) padding -> (a, b, c, d, e, f) fmtty ->
+ (a, b, c, d, e, f) padding_fmtty_ebb =
+fun pad fmtty -> match pad, fmtty with
+ | No_padding, _ -> Padding_fmtty_EBB (No_padding, fmtty)
+ | Lit_padding (padty, w), _ -> Padding_fmtty_EBB (Lit_padding (padty,w),fmtty)
+ | Arg_padding padty, Int_ty rest -> Padding_fmtty_EBB (Arg_padding padty,rest)
+ | _ -> raise Type_mismatch
+
+(* Convert a (upadding, uprecision) to a (padding, precision). *)
+(* Take one or two Int_ty from the fmtty if needed. *)
+(* Raise Type_mismatch in case of type mismatch. *)
+let type_padprec : type a b c d e f x y z .
+ (x, y) padding -> (y, z) precision -> (a, b, c, d, e, f) fmtty ->
+ (a, b, c, d, e, f) padprec_fmtty_ebb =
+fun pad prec fmtty -> match prec, type_padding pad fmtty with
+ | No_precision, Padding_fmtty_EBB (pad, rest) ->
+ Padprec_fmtty_EBB (pad, No_precision, rest)
+ | Lit_precision p, Padding_fmtty_EBB (pad, rest) ->
+ Padprec_fmtty_EBB (pad, Lit_precision p, rest)
+ | Arg_precision, Padding_fmtty_EBB (pad, Int_ty rest) ->
+ Padprec_fmtty_EBB (pad, Arg_precision, rest)
+ | _, Padding_fmtty_EBB (_, _) -> raise Type_mismatch
+
+(* Type a format according to an fmtty. *)
+(* If typing succeed, generate a copy of the format with the same
+ type parameters as the fmtty. *)
+(* Raise a Failure with an error message in case of type mismatch. *)
+let rec type_format :
+ type a1 b1 c1 d1 e1 f1
+ a2 b2 c2 d2 e2 f2 .
+ (a1, b1, c1, d1, e1, f1) fmt
+ -> (a2, b2, c2, d2, e2, f2) fmtty
+ -> (a2, b2, c2, d2, e2, f2) fmt
+= fun fmt fmtty -> match type_format_gen fmt fmtty with
+ | Fmt_fmtty_EBB (fmt', End_of_fmtty) -> fmt'
+ | _ -> raise Type_mismatch
+
+and type_format_gen :
+ type a1 b1 c1 d1 e1 f1
+ a2 b2 c2 d2 e2 f2 .
+ (a1, b1, c1, d1, e1, f1) fmt
+ -> (a2, b2, c2, d2, e2, f2) fmtty
+ -> (a2, b2, c2, d2, e2, f2) fmt_fmtty_ebb
+= fun fmt fmtty -> match fmt, fmtty with
+ | Char fmt_rest, Char_ty fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Char fmt', fmtty')
+ | Caml_char fmt_rest, Char_ty fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Caml_char fmt', fmtty')
+ | String (pad, fmt_rest), _ -> (
+ match type_padding pad fmtty with
+ | Padding_fmtty_EBB (pad, String_ty fmtty_rest) ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (String (pad, fmt'), fmtty')
+ | Padding_fmtty_EBB (_, _) -> raise Type_mismatch
+ )
+ | Caml_string (pad, fmt_rest), _ -> (
+ match type_padding pad fmtty with
+ | Padding_fmtty_EBB (pad, String_ty fmtty_rest) ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Caml_string (pad, fmt'), fmtty')
+ | Padding_fmtty_EBB (_, _) -> raise Type_mismatch
+ )
+ | Int (iconv, pad, prec, fmt_rest), _ -> (
+ match type_padprec pad prec fmtty with
+ | Padprec_fmtty_EBB (pad, prec, Int_ty fmtty_rest) ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Int (iconv, pad, prec, fmt'), fmtty')
+ | Padprec_fmtty_EBB (_, _, _) -> raise Type_mismatch
+ )
+ | Int32 (iconv, pad, prec, fmt_rest), _ -> (
+ match type_padprec pad prec fmtty with
+ | Padprec_fmtty_EBB (pad, prec, Int32_ty fmtty_rest) ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Int32 (iconv, pad, prec, fmt'), fmtty')
+ | Padprec_fmtty_EBB (_, _, _) -> raise Type_mismatch
+ )
+ | Nativeint (iconv, pad, prec, fmt_rest), _ -> (
+ match type_padprec pad prec fmtty with
+ | Padprec_fmtty_EBB (pad, prec, Nativeint_ty fmtty_rest) ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Nativeint (iconv, pad, prec, fmt'), fmtty')
+ | Padprec_fmtty_EBB (_, _, _) -> raise Type_mismatch
+ )
+ | Int64 (iconv, pad, prec, fmt_rest), _ -> (
+ match type_padprec pad prec fmtty with
+ | Padprec_fmtty_EBB (pad, prec, Int64_ty fmtty_rest) ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Int64 (iconv, pad, prec, fmt'), fmtty')
+ | Padprec_fmtty_EBB (_, _, _) -> raise Type_mismatch
+ )
+ | Float (fconv, pad, prec, fmt_rest), _ -> (
+ match type_padprec pad prec fmtty with
+ | Padprec_fmtty_EBB (pad, prec, Float_ty fmtty_rest) ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Float (fconv, pad, prec, fmt'), fmtty')
+ | Padprec_fmtty_EBB (_, _, _) -> raise Type_mismatch
+ )
+ | Bool fmt_rest, Bool_ty fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Bool fmt', fmtty')
+ | Flush fmt_rest, fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Flush fmt', fmtty')
+
+ | String_literal (str, fmt_rest), fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (String_literal (str, fmt'), fmtty')
+ | Char_literal (chr, fmt_rest), fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Char_literal (chr, fmt'), fmtty')
+
+ | Format_arg (pad_opt, sub_fmtty, fmt_rest),
+ Format_arg_ty (sub_fmtty', fmtty_rest) ->
+ if Fmtty_EBB sub_fmtty <> Fmtty_EBB sub_fmtty' then raise Type_mismatch;
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Format_arg (pad_opt, sub_fmtty', fmt'), fmtty')
+ | Format_subst (pad_opt, sub_fmtty, fmt_rest),
+ Format_subst_ty (sub_fmtty1, _sub_fmtty2, fmtty_rest) ->
+ if Fmtty_EBB (erase_rel sub_fmtty) <> Fmtty_EBB (erase_rel sub_fmtty1) then
+ raise Type_mismatch;
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest (erase_rel fmtty_rest) in
+ Fmt_fmtty_EBB (Format_subst (pad_opt, sub_fmtty1, fmt'), fmtty')
+ (* Printf and Format specific constructors: *)
+ | Alpha fmt_rest, Alpha_ty fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Alpha fmt', fmtty')
+ | Theta fmt_rest, Theta_ty fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Theta fmt', fmtty')
+
+ (* Format specific constructors: *)
+ | Formatting_lit (formatting_lit, fmt_rest), fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Formatting_lit (formatting_lit, fmt'), fmtty')
+ | Formatting_gen (formatting_gen, fmt_rest), fmtty_rest ->
+ type_formatting_gen formatting_gen fmt_rest fmtty_rest
+
+ (* Scanf specific constructors: *)
+ | Reader fmt_rest, Reader_ty fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Reader fmt', fmtty')
+ | Scan_char_set (width_opt, char_set, fmt_rest), String_ty fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Scan_char_set (width_opt, char_set, fmt'), fmtty')
+ | Scan_get_counter (counter, fmt_rest), Int_ty fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt_rest fmtty_rest in
+ Fmt_fmtty_EBB (Scan_get_counter (counter, fmt'), fmtty')
+ | Ignored_param (ign, rest), fmtty_rest ->
+ type_ignored_param ign rest fmtty_rest
+
+ | End_of_format, fmtty_rest -> Fmt_fmtty_EBB (End_of_format, fmtty_rest)
+
+ | _ -> raise Type_mismatch
+
+and type_formatting_gen : type a1 a3 b1 b3 c1 c3 d1 d3 e1 e2 e3 f1 f2 f3 .
+ (a1, b1, c1, d1, e1, f1) formatting_gen ->
+ (f1, b1, c1, e1, e2, f2) fmt ->
+ (a3, b3, c3, d3, e3, f3) fmtty ->
+ (a3, b3, c3, d3, e3, f3) fmt_fmtty_ebb =
+fun formatting_gen fmt0 fmtty0 -> match formatting_gen with
+ | Open_tag (Format (fmt1, str)) ->
+ let Fmt_fmtty_EBB (fmt2, fmtty2) = type_format_gen fmt1 fmtty0 in
+ let Fmt_fmtty_EBB (fmt3, fmtty3) = type_format_gen fmt0 fmtty2 in
+ Fmt_fmtty_EBB (Formatting_gen (Open_tag (Format (fmt2, str)), fmt3), fmtty3)
+ | Open_box (Format (fmt1, str)) ->
+ let Fmt_fmtty_EBB (fmt2, fmtty2) = type_format_gen fmt1 fmtty0 in
+ let Fmt_fmtty_EBB (fmt3, fmtty3) = type_format_gen fmt0 fmtty2 in
+ Fmt_fmtty_EBB (Formatting_gen (Open_tag (Format (fmt2, str)), fmt3), fmtty3)
+
+(* Type an Ignored_param node according to an fmtty. *)
+and type_ignored_param : type p q x y z t u v a b c d e f .
+ (x, y, z, t, q, p) ignored ->
+ (p, y, z, q, u, v) fmt ->
+ (a, b, c, d, e, f) fmtty ->
+ (a, b, c, d, e, f) fmt_fmtty_ebb =
+fun ign fmt fmtty -> match ign with
+ | Ignored_char as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_caml_char as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_string _ as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_caml_string _ as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_int _ as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_int32 _ as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_nativeint _ as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_int64 _ as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_float _ as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_bool as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_scan_char_set _ as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_scan_get_counter _ as ign' -> type_ignored_param_one ign' fmt fmtty
+ | Ignored_format_arg (pad_opt, sub_fmtty) ->
+ type_ignored_param_one (Ignored_format_arg (pad_opt, sub_fmtty)) fmt fmtty
+ | Ignored_format_subst (pad_opt, sub_fmtty) ->
+ let Fmtty_fmt_EBB (sub_fmtty', Fmt_fmtty_EBB (fmt', fmtty')) =
+ type_ignored_format_substitution sub_fmtty fmt fmtty in
+ Fmt_fmtty_EBB (Ignored_param (Ignored_format_subst (pad_opt, sub_fmtty'), fmt'), fmtty')
+ | Ignored_reader -> (
+ match fmtty with
+ | Ignored_reader_ty fmtty_rest ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt fmtty_rest in
+ Fmt_fmtty_EBB (Ignored_param (Ignored_reader, fmt'), fmtty')
+ | _ -> raise Type_mismatch
+ )
+
+and type_ignored_param_one : type a1 a2 b1 b2 c1 c2 d1 d2 e1 e2 f1 f2 .
+ (a2, b2, c2, d2, d2, a2) ignored ->
+ (a1, b1, c1, d1, e1, f1) fmt ->
+ (a2, b2, c2, d2, e2, f2) fmtty ->
+ (a2, b2, c2, d2, e2, f2) fmt_fmtty_ebb
+= fun ign fmt fmtty ->
+ let Fmt_fmtty_EBB (fmt', fmtty') = type_format_gen fmt fmtty in
+ Fmt_fmtty_EBB (Ignored_param (ign, fmt'), fmtty')
+
+(* Typing of the complex case: "%_(...%)". *)
+and type_ignored_format_substitution : type w x y z p s t u a b c d e f .
+ (w, x, y, z, s, p) fmtty ->
+ (p, x, y, s, t, u) fmt ->
+ (a, b, c, d, e, f) fmtty -> (a, b, c, d, e, f) fmtty_fmt_ebb =
+fun sub_fmtty fmt fmtty -> match sub_fmtty, fmtty with
+ | Char_ty sub_fmtty_rest, Char_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Char_ty sub_fmtty_rest', fmt')
+ | String_ty sub_fmtty_rest, String_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (String_ty sub_fmtty_rest', fmt')
+ | Int_ty sub_fmtty_rest, Int_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Int_ty sub_fmtty_rest', fmt')
+ | Int32_ty sub_fmtty_rest, Int32_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Int32_ty sub_fmtty_rest', fmt')
+ | Nativeint_ty sub_fmtty_rest, Nativeint_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Nativeint_ty sub_fmtty_rest', fmt')
+ | Int64_ty sub_fmtty_rest, Int64_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Int64_ty sub_fmtty_rest', fmt')
+ | Float_ty sub_fmtty_rest, Float_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Float_ty sub_fmtty_rest', fmt')
+ | Bool_ty sub_fmtty_rest, Bool_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Bool_ty sub_fmtty_rest', fmt')
+ | Alpha_ty sub_fmtty_rest, Alpha_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Alpha_ty sub_fmtty_rest', fmt')
+ | Theta_ty sub_fmtty_rest, Theta_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Theta_ty sub_fmtty_rest', fmt')
+ | Reader_ty sub_fmtty_rest, Reader_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Reader_ty sub_fmtty_rest', fmt')
+ | Ignored_reader_ty sub_fmtty_rest, Ignored_reader_ty fmtty_rest ->
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Ignored_reader_ty sub_fmtty_rest', fmt')
+
+ | Format_arg_ty (sub2_fmtty, sub_fmtty_rest),
+ Format_arg_ty (sub2_fmtty', fmtty_rest) ->
+ if Fmtty_EBB sub2_fmtty <> Fmtty_EBB sub2_fmtty' then raise Type_mismatch;
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution sub_fmtty_rest fmt fmtty_rest in
+ Fmtty_fmt_EBB (Format_arg_ty (sub2_fmtty', sub_fmtty_rest'), fmt')
+ | Format_subst_ty (sub1_fmtty, sub2_fmtty, sub_fmtty_rest),
+ Format_subst_ty (sub1_fmtty', sub2_fmtty', fmtty_rest) ->
+ (* TODO define Fmtty_rel_EBB to remove those erase_rel *)
+ if Fmtty_EBB (erase_rel sub1_fmtty) <> Fmtty_EBB (erase_rel sub1_fmtty') then raise Type_mismatch;
+ if Fmtty_EBB (erase_rel sub2_fmtty) <> Fmtty_EBB (erase_rel sub2_fmtty') then raise Type_mismatch;
+ let sub_fmtty' = trans (symm sub1_fmtty') sub2_fmtty' in
+ let _, f2, _, f4 = fmtty_rel_det sub_fmtty' in
+ let Refl = f2 Refl in
+ let Refl = f4 Refl in
+ let Fmtty_fmt_EBB (sub_fmtty_rest', fmt') =
+ type_ignored_format_substitution (erase_rel sub_fmtty_rest) fmt fmtty_rest in
+ Fmtty_fmt_EBB (Format_subst_ty (sub1_fmtty', sub2_fmtty', symm sub_fmtty_rest'), fmt')
+ | End_of_fmtty, fmtty ->
+ Fmtty_fmt_EBB (End_of_fmtty, type_format_gen fmt fmtty)
+ | _ -> raise Type_mismatch
+
+(* This implementation of `recast` is a bit disappointing. The
+ invariant provided by the type are very strong: the input format's
+ type is in relation to the output type's as witnessed by the
+ fmtty_rel argument. One would at first expect this function to be
+ total, and implementable by exhaustive pattern matching. Instead,
+ we reuse the highly partial and much less well-defined function
+ `type_format` that has lost all knowledge of the correspondence
+ between the argument's types.
+
+ Besides the fact that this function reuses a lot of the
+ `type_format` logic (eg.: seeing Int_ty in the fmtty parameter does
+ not let you match on Int only, as you may in fact have Float
+ (Arg_padding, ...) ("%.*d") beginning with an Int_ty), it is also
+ a partial function, because the typing information in a format is
+ not quite enough to reconstruct it unambiguously. For example, the
+ format types of "%d%_r" and "%_r%d" have the same format6
+ parameters, but they are not at all exchangeable, and putting one
+ in place of the other must result in a dynamic failure.
+
+ Given that:
+ - we'd have to duplicate a lot of non-trivial typing logic from type_format
+ - this wouldn't even eliminate (all) the dynamic failures
+ we decided to just reuse type_format directly for now.
+*)
+let recast :
+ type a1 b1 c1 d1 e1 f1
+ a2 b2 c2 d2 e2 f2
+ .
+ (a1, b1, c1, d1, e1, f1) fmt
+ -> (a1, b1, c1, d1, e1, f1,
+ a2, b2, c2, d2, e2, f2) fmtty_rel
+ -> (a2, b2, c2, d2, e2, f2) fmt
+= fun fmt fmtty ->
+ type_format fmt (erase_rel (symm fmtty))
+
+(******************************************************************************)
+ (* Printing tools *)
+
+(* Add padding spaces arround a string. *)
+let fix_padding padty width str =
+ let len = String.length str in
+ if width <= len then str else
+ let res = Bytes.make width (if padty = Zeros then '0' else ' ') in
+ begin match padty with
+ | Left -> String.blit str 0 res 0 len
+ | Right -> String.blit str 0 res (width - len) len
+ | Zeros when len > 0 && (str.[0] = '+' || str.[0] = '-' || str.[0] = ' ') ->
+ Bytes.set res 0 str.[0];
+ String.blit str 1 res (width - len + 1) (len - 1)
+ | Zeros when len > 1 && str.[0] = '0' && (str.[1] = 'x' || str.[1] = 'X') ->
+ Bytes.set res 1 str.[1];
+ String.blit str 2 res (width - len + 2) (len - 2)
+ | Zeros ->
+ String.blit str 0 res (width - len) len
+ end;
+ Bytes.unsafe_to_string res
+
+(* Add '0' padding to int, int32, nativeint or int64 string representation. *)
+let fix_int_precision prec str =
+ let len = String.length str in
+ if prec <= len then str else
+ let res = Bytes.make prec '0' in
+ begin match str.[0] with
+ | ('+' | '-' | ' ') as c ->
+ Bytes.set res 0 c;
+ String.blit str 1 res (prec - len + 1) (len - 1);
+ | '0' when len > 1 && (str.[1] = 'x' || str.[1] = 'X') ->
+ Bytes.set res 1 str.[1];
+ String.blit str 2 res (prec - len + 2) (len - 2);
+ | '0' .. '9' | 'a' .. 'f' | 'A' .. 'F' ->
+ String.blit str 0 res (prec - len) len;
+ | _ ->
+ assert false
+ end;
+ Bytes.unsafe_to_string res
+
+(* Escape a string according to the OCaml lexing convention. *)
+let string_to_caml_string str =
+ String.concat (String.escaped str) ["\""; "\""]
+
+(* Generate the format_int first argument from an int_conv. *)
+let format_of_iconv iconv = match iconv with
+ | Int_d -> "%d" | Int_pd -> "%+d" | Int_sd -> "% d"
+ | Int_i -> "%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"
+
+(* Generate the format_int32, format_nativeint and format_int64 first
+ argument from an int_conv. *)
+let format_of_aconv iconv c =
+ let seps = match iconv with
+ | Int_d -> ["%";"d"] | Int_pd -> ["%+";"d"] | Int_sd -> ["% ";"d"]
+ | Int_i -> ["%";"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"]
+ in String.concat (String.make 1 c) seps
+
+(* Generate the format_float first argument form a float_conv. *)
+let format_of_fconv fconv prec =
+ let symb = if fconv = Float_F then 'g' else char_of_fconv fconv in
+ let buf = buffer_create 16 in
+ buffer_add_char buf '%';
+ bprint_fconv_flag buf fconv;
+ buffer_add_char buf '.';
+ buffer_add_string buf (string_of_int prec);
+ buffer_add_char buf symb;
+ buffer_contents buf
+
+(* 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_aconv iconv 'l') n
+let convert_nativeint iconv n = format_nativeint (format_of_aconv iconv 'n') n
+let convert_int64 iconv n = format_int64 (format_of_aconv iconv 'L') n
+
+(* Convert a float to string. *)
+(* Fix special case of "OCaml float format". *)
+let convert_float fconv prec x =
+ let str = format_float (format_of_fconv fconv prec) x in
+ if fconv <> Float_F then str else
+ let len = String.length str in
+ let rec is_valid i =
+ if i = len then false else
+ match str.[i] with
+ | '.' | 'e' | 'E' -> true
+ | _ -> is_valid (i + 1)
+ in
+ match classify_float x with
+ | FP_normal | FP_subnormal | FP_zero ->
+ if is_valid 0 then str else str ^ "."
+ | FP_infinite ->
+ if x < 0.0 then "neg_infinity" else "infinity"
+ | FP_nan -> "nan"
+
+(* Convert a char to a string according to the OCaml lexical convention. *)
+let format_caml_char c =
+ String.concat (Char.escaped c) ["'"; "'"]
+
+(* Convert a format type to string *)
+let string_of_fmtty fmtty =
+ let buf = buffer_create 16 in
+ bprint_fmtty buf fmtty;
+ buffer_contents buf
+
+(******************************************************************************)
+ (* Generic printing function *)
+
+(* Make a generic printing function. *)
+(* Used to generate Printf and Format printing functions. *)
+(* Parameters:
+ k: a continuation finally applied to the output stream and the accumulator.
+ o: the output stream (see k, %a and %t).
+ 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 ->
+ (a, b, c, d, e, f) fmt -> a =
+fun k o acc fmt -> match fmt with
+ | Char rest ->
+ fun c ->
+ let new_acc = Acc_char (acc, c) in
+ make_printf k o new_acc rest
+ | Caml_char rest ->
+ fun c ->
+ let new_acc = Acc_string (acc, format_caml_char c) in
+ make_printf k o new_acc rest
+ | String (pad, rest) ->
+ make_string_padding k o acc rest pad (fun str -> str)
+ | Caml_string (pad, rest) ->
+ make_string_padding k o 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
+ | Int32 (iconv, pad, prec, rest) ->
+ make_int_padding_precision k o 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
+ | Int64 (iconv, pad, prec, rest) ->
+ make_int_padding_precision k o acc rest pad prec convert_int64 iconv
+ | Float (fconv, pad, prec, rest) ->
+ make_float_padding_precision k o acc rest pad prec fconv
+ | Bool rest ->
+ fun b -> make_printf k o (Acc_string (acc, string_of_bool b)) rest
+ | Alpha rest ->
+ fun f x -> make_printf k o (Acc_delay (acc, fun o -> f o x)) rest
+ | Theta rest ->
+ fun f -> make_printf k o (Acc_delay (acc, f)) rest
+ | Reader _ ->
+ (* This case is impossible, by typing of formats. *)
+ (* Indeed, since printf and co. take a format4 as argument, the 'd and 'e
+ type parameters of fmt are obviously equals. The Reader is the
+ only constructor which touch 'd and 'e type parameters of the format
+ type, it adds an (->) to the 'd parameters. Consequently, a format4
+ cannot contain a Reader node, except in the sub-format associated to
+ an %{...%}. It's not a problem because make_printf do not call
+ itself recursively on the sub-format associated to %{...%}. *)
+ assert false
+ | Flush rest ->
+ make_printf k o (Acc_flush acc) rest
+
+ | String_literal (str, rest) ->
+ make_printf k o (Acc_string (acc, str)) rest
+ | Char_literal (chr, rest) ->
+ make_printf k o (Acc_char (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_string (acc, ty)) rest)
+ | Format_subst (_, fmtty, rest) ->
+ fun (Format (fmt, _)) -> make_printf k o 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
+ | 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_string (acc, format_int "%u" n) in
+ make_printf k o new_acc rest
+ | Ignored_param (ign, rest) ->
+ make_ignored_param k o acc ign rest
+
+ | Formatting_lit (fmting_lit, rest) ->
+ make_printf k o (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'
+ | 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'
+
+ | End_of_format ->
+ k o 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 ->
+ (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
+ | 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
+
+
+(* 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 ->
+ (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
+ | 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_subst_ty (ty1, ty2, rest) ->
+ let ty = trans (symm ty1) ty2 in
+ fun _ -> make_from_fmtty k o 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 ->
+ (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
+
+(* Fix padding, take it as an extra integer argument if needed. *)
+and make_string_padding : type x z a b c d e f .
+ (b -> (b, c) acc -> f) -> b -> (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
+ | No_padding ->
+ fun x ->
+ let new_acc = Acc_string (acc, trans x) in
+ make_printf k o new_acc fmt
+ | Lit_padding (padty, width) ->
+ fun x ->
+ let new_acc = Acc_string (acc, fix_padding padty width (trans x)) in
+ make_printf k o new_acc fmt
+ | Arg_padding padty ->
+ fun w x ->
+ let new_acc = Acc_string (acc, fix_padding padty w (trans x)) in
+ make_printf k o 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 ->
+ (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
+ | No_padding, No_precision ->
+ fun x ->
+ let str = trans iconv x in
+ make_printf k o (Acc_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_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_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_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_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_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_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_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_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 ->
+ (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
+ | No_padding, No_precision ->
+ fun x ->
+ let str = convert_float fconv default_float_precision x in
+ make_printf k o (Acc_string (acc, str)) fmt
+ | No_padding, Lit_precision p ->
+ fun x ->
+ let str = convert_float fconv p x in
+ make_printf k o (Acc_string (acc, str)) fmt
+ | No_padding, Arg_precision ->
+ fun p x ->
+ let str = convert_float fconv p x in
+ make_printf k o (Acc_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_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_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_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_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_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_string (acc, str)) fmt
+
+(******************************************************************************)
+ (* Continuations for make_printf *)
+
+(* Recursively output an "accumulator" containing a reversed list of
+ printing entities (string, char, flus, ...) in an output_stream. *)
+(* Used as a continuation of make_printf. *)
+let rec output_acc o acc = match acc with
+ | Acc_formatting_lit (p, fmting_lit) ->
+ let s = string_of_formatting_lit fmting_lit in
+ output_acc o p; output_string o s;
+ | Acc_formatting_gen (p, Acc_open_tag acc') ->
+ output_acc o p; output_string o "@{"; output_acc o acc';
+ | Acc_formatting_gen (p, Acc_open_box acc') ->
+ output_acc o p; output_string o "@["; output_acc o acc';
+ | Acc_string (p, s) -> output_acc o p; output_string o s
+ | Acc_char (p, c) -> output_acc o p; output_char o c
+ | Acc_delay (p, f) -> output_acc o p; f o
+ | Acc_flush p -> output_acc o p; flush o
+ | Acc_invalid_arg (p, msg) -> output_acc o p; invalid_arg msg;
+ | End_of_acc -> ()
+
+(* Recursively output an "accumulator" containing a reversed list of
+ printing entities (string, char, flus, ...) in a buffer. *)
+(* Used as a continuation of make_printf. *)
+let rec bufput_acc b acc = match acc with
+ | Acc_formatting_lit (p, fmting_lit) ->
+ let s = string_of_formatting_lit fmting_lit in
+ bufput_acc b p; Buffer.add_string b s;
+ | Acc_formatting_gen (p, Acc_open_tag acc') ->
+ bufput_acc b p; Buffer.add_string b "@{"; bufput_acc b acc';
+ | Acc_formatting_gen (p, Acc_open_box acc') ->
+ bufput_acc b p; Buffer.add_string b "@["; bufput_acc b acc';
+ | Acc_string (p, s) -> bufput_acc b p; Buffer.add_string b s
+ | Acc_char (p, c) -> bufput_acc b p; Buffer.add_char b c
+ | Acc_delay (p, f) -> bufput_acc b p; f b
+ | Acc_flush p -> bufput_acc b p;
+ | Acc_invalid_arg (p, msg) -> bufput_acc b p; invalid_arg msg;
+ | End_of_acc -> ()
+
+(* Recursively output an "accumulator" containing a reversed list of
+ printing entities (string, char, flus, ...) in a buffer. *)
+(* Differ from bufput_acc by the interpretation of %a and %t. *)
+(* Used as a continuation of make_printf. *)
+let rec strput_acc b acc = match acc with
+ | Acc_formatting_lit (p, fmting_lit) ->
+ let s = string_of_formatting_lit fmting_lit in
+ strput_acc b p; Buffer.add_string b s;
+ | Acc_formatting_gen (p, Acc_open_tag acc') ->
+ strput_acc b p; Buffer.add_string b "@{"; strput_acc b acc';
+ | Acc_formatting_gen (p, Acc_open_box acc') ->
+ strput_acc b p; Buffer.add_string b "@["; strput_acc b acc';
+ | Acc_string (p, s) -> strput_acc b p; Buffer.add_string b s
+ | Acc_char (p, c) -> strput_acc b p; Buffer.add_char b c
+ | Acc_delay (p, f) -> strput_acc b p; Buffer.add_string b (f ())
+ | Acc_flush p -> strput_acc b p;
+ | Acc_invalid_arg (p, msg) -> strput_acc b p; invalid_arg msg;
+ | End_of_acc -> ()
+
+(******************************************************************************)
+ (* Error managment *)
+
+(* Raise a 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
+
+(******************************************************************************)
+ (* Formatting tools *)
+
+(* Convert a string to an open block description (indent, block_type) *)
+let open_box_of_string str =
+ if str = "" then (0, Pp_box) else
+ let len = String.length str in
+ let invalid_box () = failwith_message "invalid box description %S" str in
+ let rec parse_spaces i =
+ if i = len then i else
+ match str.[i] with
+ | ' ' | '\t' -> parse_spaces (i + 1)
+ | _ -> i
+ and parse_lword i j =
+ if j = len then j else
+ match str.[j] with
+ | 'a' .. 'z' -> parse_lword i (j + 1)
+ | _ -> j
+ and parse_int i j =
+ if j = len then j else
+ match str.[j] with
+ | '0' .. '9' | '-' -> parse_int i (j + 1)
+ | _ -> j in
+ let wstart = parse_spaces 0 in
+ let wend = parse_lword wstart wstart in
+ let box_name = String.sub str wstart (wend - wstart) in
+ let nstart = parse_spaces wend in
+ let nend = parse_int nstart nstart in
+ let indent =
+ if nstart = nend then 0 else
+ try int_of_string (String.sub str nstart (nend - nstart))
+ with Failure _ -> invalid_box () in
+ let exp_end = parse_spaces nend in
+ let () = if exp_end <> len then invalid_box () in
+ let box_type = match box_name with
+ | "" | "b" -> Pp_box
+ | "h" -> Pp_hbox
+ | "v" -> Pp_vbox
+ | "hv" -> Pp_hvbox
+ | "hov" -> Pp_hovbox
+ | _ -> invalid_box () in
+ (indent, box_type)
+
+(******************************************************************************)
+ (* Parsing tools *)
+
+(* Create a padding_fmt_ebb from a padding and a format. *)
+(* Copy the padding to disjoin the type parameters of argument and result. *)
+let make_padding_fmt_ebb : type x y .
+ (x, y) padding -> (_, _, _, _, _, _) fmt ->
+ (_, _, _, _, _) padding_fmt_ebb =
+fun pad fmt -> match pad with
+ | No_padding -> Padding_fmt_EBB (No_padding, fmt)
+ | Lit_padding (s, w) -> Padding_fmt_EBB (Lit_padding (s, w), fmt)
+ | Arg_padding s -> Padding_fmt_EBB (Arg_padding s, fmt)
+
+(* Create a precision_fmt_ebb from a precision and a format. *)
+(* Copy the precision to disjoin the type parameters of argument and result. *)
+let make_precision_fmt_ebb : type x y .
+ (x, y) precision -> (_, _, _, _, _, _) fmt ->
+ (_, _, _, _, _) precision_fmt_ebb =
+fun prec fmt -> match prec with
+ | No_precision -> Precision_fmt_EBB (No_precision, fmt)
+ | Lit_precision p -> Precision_fmt_EBB (Lit_precision p, fmt)
+ | Arg_precision -> Precision_fmt_EBB (Arg_precision, fmt)
+
+(* Create a padprec_fmt_ebb forma a padding, a precision and a format. *)
+(* Copy the padding and the precision to disjoin type parameters of arguments
+ and result. *)
+let make_padprec_fmt_ebb : type x y z t .
+ (x, y) padding -> (z, t) precision ->
+ (_, _, _, _, _, _) fmt ->
+ (_, _, _, _, _) padprec_fmt_ebb =
+fun pad prec fmt ->
+ let Precision_fmt_EBB (prec, fmt') = make_precision_fmt_ebb prec fmt in
+ match pad with
+ | No_padding -> Padprec_fmt_EBB (No_padding, prec, fmt')
+ | Lit_padding (s, w) -> Padprec_fmt_EBB (Lit_padding (s, w), prec, fmt')
+ | Arg_padding s -> Padprec_fmt_EBB (Arg_padding s, prec, fmt')
+
+(******************************************************************************)
+ (* Format parsing *)
+
+(* Parse a string representing a format and create a fmt_ebb. *)
+(* Raise an Failure exception in case of invalid format. *)
+let fmt_ebb_of_string str =
+ (* Parameters naming convention: *)
+ (* - lit_start: start of the literal sequence. *)
+ (* - str_ind: current index in the string. *)
+ (* - end_ind: end of the current (sub-)format. *)
+ (* - pct_ind: index of the '%' in the current micro-format. *)
+ (* - zero: is the '0' flag defined in the current micro-format. *)
+ (* - minus: is the '-' flag defined in the current micro-format. *)
+ (* - plus: is the '+' flag defined in the current micro-format. *)
+ (* - sharp: is the '#' flag defined in the current micro-format. *)
+ (* - space: is the ' ' flag defined in the current micro-format. *)
+ (* - ign: is the '_' flag defined in the current micro-format. *)
+ (* - pad: padding of the current micro-format. *)
+ (* - prec: precision of the current micro-format. *)
+ (* - symb: char representing the conversion ('c', 's', 'd', ...). *)
+ (* - char_set: set of characters as bitmap (see scanf %[...]). *)
+
+ (* Raise a Failure with a friendly error message. *)
+ (* Used when the end of the format (or the current sub-format) was encoutered
+ unexpectedly. *)
+ let unexpected_end_of_format end_ind =
+ failwith_message
+ "invalid format %S: at character number %d, unexpected end of format"
+ str end_ind;
+
+ (* Raise Failure with a friendly error message about an option dependencie
+ problem. *)
+ and invalid_format_without str_ind c s =
+ failwith_message
+ "invalid format %S: at character number %d, '%c' without %s"
+ str str_ind c s
+
+ (* Raise Failure with a friendly error message about an unexpected
+ character. *)
+ and expected_character str_ind expected read =
+ failwith_message
+ "invalid format %S: at character number %d, %s expected, read %C"
+ str str_ind expected read in
+
+ (* Parse the string from beg_ind (included) to end_ind (excluded). *)
+ let rec parse : type e f . int -> int -> (_, _, e, f) fmt_ebb =
+ fun beg_ind end_ind -> parse_literal beg_ind beg_ind end_ind
+
+ (* Read literal characters up to '%' or '@' special characters. *)
+ and parse_literal : type e f . int -> int -> int -> (_, _, e, f) fmt_ebb =
+ fun lit_start str_ind end_ind ->
+ if str_ind = end_ind then add_literal lit_start str_ind End_of_format else
+ match str.[str_ind] with
+ | '%' ->
+ let Fmt_EBB fmt_rest = parse_format str_ind end_ind in
+ add_literal lit_start str_ind fmt_rest
+ | '@' ->
+ let Fmt_EBB fmt_rest = parse_after_at (str_ind + 1) end_ind in
+ add_literal lit_start str_ind fmt_rest
+ | _ ->
+ parse_literal lit_start (str_ind + 1) end_ind
+
+ (* Parse a format after '%' *)
+ and parse_format : type e f . int -> int -> (_, _, e, f) fmt_ebb =
+ fun pct_ind end_ind -> parse_ign pct_ind (pct_ind + 1) end_ind
+
+ and parse_ign : type e f . int -> int -> int -> (_, _, e, f) fmt_ebb =
+ fun pct_ind str_ind end_ind ->
+ match str.[str_ind] with
+ | '_' -> parse_flags pct_ind (str_ind+1) end_ind true
+ | _ -> parse_flags pct_ind str_ind end_ind false
+
+ and parse_flags : type e f . int -> int -> int -> bool -> (_, _, e, f) fmt_ebb =
+ fun pct_ind str_ind end_ind ign ->
+ let zero = ref false and minus = ref false
+ and plus = ref false and space = ref false
+ and sharp = ref false in
+ let set_flag str_ind flag =
+ (* in legacy mode, duplicate flags are accepted *)
+ if !flag && not legacy_behavior then
+ failwith_message
+ "invalid format %S: at character number %d, duplicate flag %C"
+ str str_ind str.[str_ind];
+ flag := true;
+ in
+ let rec read_flags str_ind =
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ begin match str.[str_ind] with
+ | '0' -> set_flag str_ind zero; read_flags (str_ind + 1)
+ | '-' -> set_flag str_ind minus; read_flags (str_ind + 1)
+ | '+' -> set_flag str_ind plus; read_flags (str_ind + 1)
+ | '#' -> set_flag str_ind sharp; read_flags (str_ind + 1)
+ | ' ' -> set_flag str_ind space; read_flags (str_ind + 1)
+ | _ ->
+ parse_padding pct_ind str_ind end_ind
+ !zero !minus !plus !sharp !space ign
+ end
+ in
+ read_flags str_ind
+
+ (* Try to read a digital or a '*' padding. *)
+ and parse_padding : type e f .
+ int -> int -> int -> bool -> bool -> bool -> bool -> bool -> bool ->
+ (_, _, e, f) fmt_ebb =
+ fun pct_ind str_ind end_ind zero minus plus sharp space ign ->
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ let padty = match zero, minus with
+ | false, false -> Right
+ | false, true -> Left
+ | true, false -> Zeros
+ | true, true ->
+ if legacy_behavior then Left
+ else incompatible_flag pct_ind str_ind '-' "0" in
+ match str.[str_ind] with
+ | '0' .. '9' ->
+ let new_ind, width = parse_positive str_ind end_ind 0 in
+ parse_after_padding pct_ind new_ind end_ind plus sharp space ign
+ (Lit_padding (padty, width))
+ | '*' ->
+ parse_after_padding pct_ind (str_ind + 1) end_ind plus sharp space ign
+ (Arg_padding padty)
+ | _ ->
+ if legacy_behavior then
+ parse_after_padding pct_ind str_ind end_ind plus sharp space ign
+ No_padding
+ else begin match padty with
+ | Left ->
+ invalid_format_without (str_ind - 1) '-' "padding"
+ | Zeros ->
+ invalid_format_without (str_ind - 1) '0' "padding"
+ | Right ->
+ parse_after_padding pct_ind str_ind end_ind plus sharp space ign
+ No_padding
+ end
+
+ (* Is precision defined? *)
+ and parse_after_padding : type x e f .
+ int -> int -> int -> bool -> bool -> bool -> bool -> (x, _) padding ->
+ (_, _, e, f) fmt_ebb =
+ fun pct_ind str_ind end_ind plus sharp space ign pad ->
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ match str.[str_ind] with
+ | '.' ->
+ parse_precision pct_ind (str_ind + 1) end_ind plus sharp space ign pad
+ | symb ->
+ parse_conversion pct_ind (str_ind + 1) end_ind plus sharp space ign pad
+ No_precision symb
+
+ (* Read the digital or '*' precision. *)
+ and parse_precision : type x e f .
+ int -> int -> int -> bool -> bool -> bool -> bool -> (x, _) padding ->
+ (_, _, e, f) fmt_ebb =
+ fun pct_ind str_ind end_ind plus sharp space ign pad ->
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ let parse_literal str_ind =
+ let new_ind, prec = parse_positive str_ind end_ind 0 in
+ parse_conversion pct_ind (new_ind + 1) end_ind plus sharp space ign pad
+ (Lit_precision prec) str.[new_ind] in
+ match str.[str_ind] with
+ | '0' .. '9' -> parse_literal str_ind
+ | ('+' | '-') when legacy_behavior ->
+ (* Legacy mode would accept and ignore '+' or '-' before the
+ integer describing the desired precision; not that this
+ cannot happen for padding width, as '+' and '-' already have
+ a semantics there.
+
+ That said, the idea (supported by this tweak) that width and
+ precision literals are "integer literals" in the OCaml sense is
+ still blatantly wrong, as 123_456 or 0xFF are rejected. *)
+ parse_literal (str_ind + 1)
+ | '*' ->
+ parse_after_precision pct_ind (str_ind + 1) end_ind plus sharp space ign
+ pad Arg_precision
+ | _ ->
+ if legacy_behavior then
+ (* note that legacy implementation did not ignore '.' without
+ a number (as it does for padding indications), but
+ interprets it as '.0' *)
+ parse_after_precision pct_ind str_ind end_ind plus sharp space ign pad (Lit_precision 0) else
+ invalid_format_without (str_ind - 1) '.' "precision"
+
+ (* Try to read the conversion. *)
+ and parse_after_precision : type x z e f .
+ int -> int -> int -> bool -> bool -> bool -> bool -> (x, _) padding ->
+ (z, _) precision -> (_, _, e, f) fmt_ebb =
+ fun pct_ind str_ind end_ind plus sharp space ign pad prec ->
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ parse_conversion pct_ind (str_ind + 1) end_ind plus sharp space ign pad prec
+ str.[str_ind]
+
+ (* Case analysis on conversion. *)
+ and parse_conversion : type x y z t e f .
+ int -> int -> int -> bool -> bool -> bool -> bool -> (x, y) padding ->
+ (z, t) precision -> char -> (_, _, e, f) fmt_ebb =
+ fun pct_ind str_ind end_ind plus sharp space ign pad prec symb ->
+ (* Flags used to check option usages/compatibilities. *)
+ let plus_used = ref false and sharp_used = ref false
+ and space_used = ref false and ign_used = ref false
+ and pad_used = ref false and prec_used = ref false in
+
+ (* Access to options, update flags. *)
+ let get_plus () = plus_used := true; plus
+ and get_sharp () = sharp_used := true; sharp
+ and get_space () = space_used := true; space
+ and get_ign () = ign_used := true; ign
+ and get_pad () = pad_used := true; pad
+ and get_prec () = prec_used := true; prec in
+
+ (* Check that padty <> Zeros. *)
+ let check_no_0 symb (type a) (type b) (pad : (a,b) padding) =
+ match pad with
+ | No_padding -> pad
+ | Lit_padding ((Left | Right), _) -> pad
+ | Arg_padding (Left | Right) -> pad
+ | Lit_padding (Zeros, width) ->
+ if legacy_behavior then Lit_padding (Right, width)
+ else incompatible_flag pct_ind str_ind symb "0"
+ | Arg_padding Zeros ->
+ if legacy_behavior then Arg_padding Right
+ else incompatible_flag pct_ind str_ind symb "0"
+ in
+
+ (* Get padding as a pad_option (see "%_", "%{", "%(" and "%[").
+ (no need for legacy mode tweaking, those were rejected by the
+ legacy parser as well) *)
+ let get_pad_opt c = match get_pad () with
+ | No_padding -> None
+ | Lit_padding (Right, width) -> Some width
+ | Lit_padding (Zeros, width) ->
+ if legacy_behavior then Some width
+ else incompatible_flag pct_ind str_ind c "'0'"
+ | Lit_padding (Left, width) ->
+ if legacy_behavior then Some width
+ else incompatible_flag pct_ind str_ind c "'-'"
+ | Arg_padding _ -> incompatible_flag pct_ind str_ind c "'*'"
+ in
+
+ (* Get precision as a prec_option (see "%_f").
+ (no need for legacy mode tweaking, those were rejected by the
+ legacy parser as well) *)
+ let get_prec_opt () = match get_prec () with
+ | No_precision -> None
+ | Lit_precision ndec -> Some ndec
+ | Arg_precision -> incompatible_flag pct_ind str_ind '_' "'*'"
+ in
+
+ let fmt_result = match symb with
+ | ',' ->
+ parse str_ind end_ind
+ | 'c' ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ if get_ign () then Fmt_EBB (Ignored_param (Ignored_char, fmt_rest))
+ else Fmt_EBB (Char fmt_rest)
+ | 'C' ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ if get_ign () then Fmt_EBB (Ignored_param (Ignored_caml_char,fmt_rest))
+ else Fmt_EBB (Caml_char fmt_rest)
+ | 's' ->
+ let pad = check_no_0 symb (get_pad ()) in
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ if get_ign () then
+ let ignored = Ignored_string (get_pad_opt '_') in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ let Padding_fmt_EBB (pad', fmt_rest') =
+ make_padding_fmt_ebb pad fmt_rest in
+ Fmt_EBB (String (pad', fmt_rest'))
+ | 'S' ->
+ let pad = check_no_0 symb (get_pad ()) in
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ if get_ign () then
+ let ignored = Ignored_caml_string (get_pad_opt '_') in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ let Padding_fmt_EBB (pad', fmt_rest') =
+ make_padding_fmt_ebb pad fmt_rest in
+ Fmt_EBB (Caml_string (pad', fmt_rest'))
+ | 'd' | 'i' | 'x' | 'X' | 'o' | 'u' ->
+ let iconv = compute_int_conv pct_ind str_ind (get_plus ()) (get_sharp ())
+ (get_space ()) symb in
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ if get_ign () then
+ let ignored = Ignored_int (iconv, get_pad_opt '_') in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ let Padprec_fmt_EBB (pad', prec', fmt_rest') =
+ make_padprec_fmt_ebb (get_pad ()) (get_prec ()) fmt_rest in
+ Fmt_EBB (Int (iconv, pad', prec', fmt_rest'))
+ | 'N' ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ let counter = Token_counter in
+ if get_ign () then
+ let ignored = Ignored_scan_get_counter counter in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ Fmt_EBB (Scan_get_counter (counter, fmt_rest))
+ | 'l' | 'n' | 'L' when str_ind=end_ind || not (is_int_base str.[str_ind]) ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ let counter = counter_of_char symb in
+ if get_ign () then
+ let ignored = Ignored_scan_get_counter counter in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ Fmt_EBB (Scan_get_counter (counter, fmt_rest))
+ | 'l' ->
+ let iconv =
+ compute_int_conv pct_ind (str_ind + 1) (get_plus ()) (get_sharp ())
+ (get_space ()) str.[str_ind] in
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ if get_ign () then
+ let ignored = Ignored_int32 (iconv, get_pad_opt '_') in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ let Padprec_fmt_EBB (pad', prec', fmt_rest') =
+ make_padprec_fmt_ebb (get_pad ()) (get_prec ()) fmt_rest in
+ Fmt_EBB (Int32 (iconv, pad', prec', fmt_rest'))
+ | 'n' ->
+ let iconv =
+ compute_int_conv pct_ind (str_ind + 1) (get_plus ())
+ (get_sharp ()) (get_space ()) str.[str_ind] in
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ if get_ign () then
+ let ignored = Ignored_nativeint (iconv, get_pad_opt '_') in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ let Padprec_fmt_EBB (pad', prec', fmt_rest') =
+ make_padprec_fmt_ebb (get_pad ()) (get_prec ()) fmt_rest in
+ Fmt_EBB (Nativeint (iconv, pad', prec', fmt_rest'))
+ | 'L' ->
+ let iconv =
+ compute_int_conv pct_ind (str_ind + 1) (get_plus ()) (get_sharp ())
+ (get_space ()) str.[str_ind] in
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ if get_ign () then
+ let ignored = Ignored_int64 (iconv, get_pad_opt '_') in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ let Padprec_fmt_EBB (pad', prec', fmt_rest') =
+ make_padprec_fmt_ebb (get_pad ()) (get_prec ()) fmt_rest in
+ Fmt_EBB (Int64 (iconv, pad', prec', fmt_rest'))
+ | 'f' | 'e' | 'E' | 'g' | 'G' | 'F' ->
+ let fconv = compute_float_conv pct_ind str_ind (get_plus ())
+ (get_space ()) symb in
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ if get_ign () then
+ let ignored = Ignored_float (get_pad_opt '_', get_prec_opt ()) in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ let Padprec_fmt_EBB (pad', prec', fmt_rest') =
+ make_padprec_fmt_ebb (get_pad ()) (get_prec ()) fmt_rest in
+ Fmt_EBB (Float (fconv, pad', prec', fmt_rest'))
+ | 'b' | 'B' ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ if get_ign () then Fmt_EBB (Ignored_param (Ignored_bool, fmt_rest))
+ else Fmt_EBB (Bool fmt_rest)
+ | 'a' ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ Fmt_EBB (Alpha fmt_rest)
+ | 't' ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ Fmt_EBB (Theta fmt_rest)
+ | 'r' ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ if get_ign () then Fmt_EBB (Ignored_param (Ignored_reader, fmt_rest))
+ else Fmt_EBB (Reader fmt_rest)
+ | '!' ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ Fmt_EBB (Flush fmt_rest)
+ | ('%' | '@') as c ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ Fmt_EBB (Char_literal (c, fmt_rest))
+ | '{' ->
+ let sub_end = search_subformat_end str_ind end_ind '}' in
+ let Fmt_EBB sub_fmt = parse str_ind sub_end in
+ let Fmt_EBB fmt_rest = parse (sub_end + 2) end_ind in
+ let sub_fmtty = fmtty_of_fmt sub_fmt in
+ if get_ign () then
+ let ignored = Ignored_format_arg (get_pad_opt '_', sub_fmtty) in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ Fmt_EBB (Format_arg (get_pad_opt '{', sub_fmtty, fmt_rest))
+ | '(' ->
+ let sub_end = search_subformat_end str_ind end_ind ')' in
+ let Fmt_EBB fmt_rest = parse (sub_end + 2) end_ind in
+ let Fmt_EBB sub_fmt = parse str_ind sub_end in
+ let sub_fmtty = fmtty_of_fmt sub_fmt in
+ if get_ign () then
+ let ignored = Ignored_format_subst (get_pad_opt '_', sub_fmtty) in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ Fmt_EBB (Format_subst (get_pad_opt '(', sub_fmtty, fmt_rest))
+ | '[' ->
+ let next_ind, char_set = parse_char_set str_ind end_ind in
+ let Fmt_EBB fmt_rest = parse next_ind end_ind in
+ if get_ign () then
+ let ignored = Ignored_scan_char_set (get_pad_opt '_', char_set) in
+ Fmt_EBB (Ignored_param (ignored, fmt_rest))
+ else
+ Fmt_EBB (Scan_char_set (get_pad_opt '[', char_set, fmt_rest))
+ | '-' | '+' | '#' | ' ' | '_' ->
+ failwith_message
+ "invalid format %S: at character number %d, \
+ flag %C is only allowed after the '%%', before padding and precision"
+ str pct_ind symb
+ | _ ->
+ failwith_message
+ "invalid format %S: at character number %d, \
+ invalid conversion \"%%%c\"" str (str_ind - 1) symb
+ in
+ (* Check for unused options, and reject them as incompatible.
+
+ Such checks need to be disabled in legacy mode, as the legacy
+ parser silently ignored incompatible flags. *)
+ if not legacy_behavior then begin
+ if not !plus_used && plus then
+ incompatible_flag pct_ind str_ind symb "'+'";
+ if not !sharp_used && sharp then
+ incompatible_flag pct_ind str_ind symb "'#'";
+ if not !space_used && space then
+ incompatible_flag pct_ind str_ind symb "' '";
+ if not !pad_used && Padding_EBB pad <> Padding_EBB No_padding then
+ incompatible_flag pct_ind str_ind symb "`padding'";
+ if not !prec_used && Precision_EBB prec <> Precision_EBB No_precision then
+ incompatible_flag pct_ind str_ind (if ign then '_' else symb)
+ "`precision'";
+ if ign && plus then incompatible_flag pct_ind str_ind '_' "'+'";
+ end;
+ (* this last test must not be disabled in legacy mode,
+ as ignoring it would typically result in a different typing
+ than what the legacy parser used *)
+ if not !ign_used && ign then
+ begin match symb with
+ (* argument-less formats can safely be ignored in legacy mode *)
+ | ('@' | '%' | '!' | ',') when legacy_behavior -> ()
+ | _ ->
+ incompatible_flag pct_ind str_ind symb "'_'"
+ end;
+ fmt_result
+
+ (* Parse formatting informations (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))
+ else
+ match str.[str_ind] with
+ | '[' ->
+ parse_tag false (str_ind + 1) end_ind
+ | ']' ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ Fmt_EBB (Formatting_lit (Close_box, fmt_rest))
+ | '{' ->
+ parse_tag true (str_ind + 1) end_ind
+ | '}' ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ Fmt_EBB (Formatting_lit (Close_tag, fmt_rest))
+ | ',' ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ Fmt_EBB (Formatting_lit (Break ("@,", 0, 0), fmt_rest))
+ | ' ' ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ Fmt_EBB (Formatting_lit (Break ("@ ", 1, 0), fmt_rest))
+ | ';' ->
+ parse_good_break (str_ind + 1) end_ind
+ | '?' ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ Fmt_EBB (Formatting_lit (FFlush, fmt_rest))
+ | '\n' ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ Fmt_EBB (Formatting_lit (Force_newline, fmt_rest))
+ | '.' ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ Fmt_EBB (Formatting_lit (Flush_newline, fmt_rest))
+ | '<' ->
+ parse_magic_size (str_ind + 1) end_ind
+ | '@' ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ Fmt_EBB (Formatting_lit (Escaped_at, fmt_rest))
+ | '%' when str_ind + 1 < end_ind && str.[str_ind + 1] = '%' ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 2) end_ind in
+ Fmt_EBB (Formatting_lit (Escaped_percent, fmt_rest))
+ | '%' ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ Fmt_EBB (Char_literal ('@', fmt_rest))
+ | c ->
+ let Fmt_EBB fmt_rest = parse (str_ind + 1) end_ind in
+ Fmt_EBB (Formatting_lit (Scan_indic c, fmt_rest))
+
+ and check_open_box : type a b c d e f . (a, b, c, d, e, f) fmt -> unit =
+ fun fmt -> match fmt with
+ | String_literal (str, End_of_format) -> (
+ try ignore (open_box_of_string str) with Failure _ ->
+ ((* Emit warning: invalid open box *))
+ )
+ | _ -> ()
+
+ (* Try to read the optionnal <name> after "@{" or "@[". *)
+ and parse_tag : type e f . bool -> int -> int -> (_, _, e, f) fmt_ebb =
+ fun is_open_tag str_ind end_ind ->
+ try
+ if str_ind = end_ind then raise Not_found;
+ match str.[str_ind] with
+ | '<' ->
+ let ind = String.index_from str (str_ind + 1) '>' in
+ if ind >= end_ind then raise Not_found;
+ let sub_str = String.sub str str_ind (ind - str_ind + 1) in
+ let Fmt_EBB fmt_rest = parse (ind + 1) end_ind in
+ let Fmt_EBB sub_fmt = parse str_ind (ind + 1) in
+ let sub_format = Format (sub_fmt, sub_str) in
+ let formatting = if is_open_tag then Open_tag sub_format else (
+ check_open_box sub_fmt;
+ Open_box sub_format) in
+ Fmt_EBB (Formatting_gen (formatting, fmt_rest))
+ | _ ->
+ raise Not_found
+ with Not_found ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ let sub_format = Format (End_of_format, "") in
+ let formatting =
+ if is_open_tag then Open_tag sub_format else Open_box sub_format in
+ Fmt_EBB (Formatting_gen (formatting, fmt_rest))
+
+ (* Try to read the optionnal <width offset> after "@;". *)
+ and parse_good_break : type e f . int -> int -> (_, _, e, f) fmt_ebb =
+ fun str_ind end_ind ->
+ let next_ind, formatting_lit =
+ try
+ if str_ind = end_ind || str.[str_ind] <> '<' then raise Not_found;
+ let str_ind_1 = parse_spaces (str_ind + 1) end_ind in
+ match str.[str_ind_1] with
+ | '0' .. '9' | '-' -> (
+ let str_ind_2, width = parse_integer str_ind_1 end_ind in
+ let str_ind_3 = parse_spaces str_ind_2 end_ind in
+ match str.[str_ind_3] with
+ | '>' ->
+ let s = String.sub str (str_ind-2) (str_ind_3-str_ind+3) in
+ str_ind_3 + 1, Break (s, width, 0)
+ | '0' .. '9' | '-' ->
+ let str_ind_4, offset = parse_integer str_ind_3 end_ind in
+ let str_ind_5 = parse_spaces str_ind_4 end_ind in
+ if str.[str_ind_5] <> '>' then raise Not_found;
+ let s = String.sub str (str_ind-2) (str_ind_5-str_ind+3) in
+ str_ind_5 + 1, Break (s, width, offset)
+ | _ -> raise Not_found
+ )
+ | _ -> raise Not_found
+ with Not_found | Failure _ ->
+ str_ind, Break ("@;", 1, 0)
+ in
+ let Fmt_EBB fmt_rest = parse next_ind end_ind in
+ Fmt_EBB (Formatting_lit (formatting_lit, fmt_rest))
+
+ (* Parse the size in a <n>. *)
+ and parse_magic_size : type e f . int -> int -> (_, _, e, f) fmt_ebb =
+ fun str_ind end_ind ->
+ match
+ try
+ let str_ind_1 = parse_spaces str_ind end_ind in
+ match str.[str_ind_1] with
+ | '0' .. '9' | '-' ->
+ let str_ind_2, size = parse_integer str_ind_1 end_ind in
+ let str_ind_3 = parse_spaces str_ind_2 end_ind in
+ if str.[str_ind_3] <> '>' then raise Not_found;
+ let s = String.sub str (str_ind - 2) (str_ind_3 - str_ind + 3) in
+ Some (str_ind_3 + 1, Magic_size (s, size))
+ | _ -> None
+ with Not_found | Failure _ ->
+ None
+ with
+ | Some (next_ind, formatting_lit) ->
+ let Fmt_EBB fmt_rest = parse next_ind end_ind in
+ Fmt_EBB (Formatting_lit (formatting_lit, fmt_rest))
+ | None ->
+ let Fmt_EBB fmt_rest = parse str_ind end_ind in
+ Fmt_EBB (Formatting_lit (Scan_indic '<', fmt_rest))
+
+ (* Parse and construct a char set. *)
+ and parse_char_set str_ind end_ind =
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+
+ let char_set = create_char_set () in
+ let add_char c =
+ add_in_char_set char_set c;
+ in
+ let add_range c c' =
+ for i = int_of_char c to int_of_char c' do
+ add_in_char_set char_set (char_of_int i);
+ done;
+ in
+
+ let fail_single_percent str_ind =
+ failwith_message
+ "invalid format %S: '%%' alone is not accepted in character sets, \
+ use %%%% instead at position %d." str str_ind;
+ in
+
+ (* Parse the first character of a char set. *)
+ let rec parse_char_set_start str_ind end_ind =
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ let c = str.[str_ind] in
+ parse_char_set_after_char (str_ind + 1) end_ind c;
+
+ (* Parse the content of a char set until the first ']'. *)
+ and parse_char_set_content str_ind end_ind =
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ match str.[str_ind] with
+ | ']' ->
+ str_ind + 1
+ | '-' ->
+ add_char '-';
+ parse_char_set_content (str_ind + 1) end_ind;
+ | c ->
+ parse_char_set_after_char (str_ind + 1) end_ind c;
+
+ (* Test for range in char set. *)
+ and parse_char_set_after_char str_ind end_ind c =
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ match str.[str_ind] with
+ | ']' ->
+ add_char c;
+ str_ind + 1
+ | '-' ->
+ parse_char_set_after_minus (str_ind + 1) end_ind c
+ | ('%' | '@') as c' when c = '%' ->
+ add_char c';
+ parse_char_set_content (str_ind + 1) end_ind
+ | c' ->
+ if c = '%' then fail_single_percent str_ind;
+ (* note that '@' alone is accepted, as done by the legacy implementation;
+ the documentation specifically requires %@ so we could warn on that *)
+ add_char c;
+ parse_char_set_after_char (str_ind + 1) end_ind c'
+
+ (* Manage range in char set (except if the '-' the last char before ']') *)
+ and parse_char_set_after_minus str_ind end_ind c =
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ match str.[str_ind] with
+ | ']' ->
+ add_char c;
+ add_char '-';
+ str_ind + 1
+ | '%' ->
+ if str_ind + 1 = end_ind then unexpected_end_of_format end_ind;
+ begin match str.[str_ind + 1] with
+ | ('%' | '@') as c' ->
+ add_range c c';
+ parse_char_set_content (str_ind + 2) end_ind
+ | _ -> fail_single_percent str_ind
+ end
+ | c' ->
+ add_range c c';
+ parse_char_set_content (str_ind + 1) end_ind
+ in
+ let str_ind, reverse =
+ match str.[str_ind] with
+ | '^' -> str_ind + 1, true
+ | _ -> str_ind, false in
+ let next_ind = parse_char_set_start str_ind end_ind in
+ let char_set = freeze_char_set char_set in
+ next_ind, (if reverse then rev_char_set char_set else char_set)
+
+ (* Consume all next spaces, raise an Failure if end_ind is reached. *)
+ and parse_spaces str_ind end_ind =
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ if str.[str_ind] = ' ' then parse_spaces (str_ind + 1) end_ind else str_ind
+
+ (* Read a positive integer from the string, raise a Failure if end_ind is
+ reached. *)
+ and parse_positive str_ind end_ind acc =
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ match str.[str_ind] with
+ | '0' .. '9' as c ->
+ let new_acc = acc * 10 + (int_of_char c - int_of_char '0') in
+ if new_acc > Sys.max_string_length then
+ failwith_message
+ "invalid format %S: integer %d is greater than the limit %d"
+ str new_acc Sys.max_string_length
+ else
+ parse_positive (str_ind + 1) end_ind new_acc
+ | _ -> str_ind, acc
+
+ (* Read a positive or negative integer from the string, raise a Failure
+ if end_ind is reached. *)
+ and parse_integer str_ind end_ind =
+ if str_ind = end_ind then unexpected_end_of_format end_ind;
+ match str.[str_ind] with
+ | '0' .. '9' -> parse_positive str_ind end_ind 0
+ | '-' -> (
+ if str_ind + 1 = end_ind then unexpected_end_of_format end_ind;
+ match str.[str_ind + 1] with
+ | '0' .. '9' ->
+ let next_ind, n = parse_positive (str_ind + 1) end_ind 0 in
+ next_ind, -n
+ | c ->
+ expected_character (str_ind + 1) "digit" c
+ )
+ | _ -> assert false
+
+ (* Add a literal to a format from a literal character sub-sequence. *)
+ and add_literal : type a d e f .
+ int -> int -> (a, _, _, d, e, f) fmt ->
+ (_, _, e, f) fmt_ebb =
+ fun lit_start str_ind fmt -> match str_ind - lit_start with
+ | 0 -> Fmt_EBB fmt
+ | 1 -> Fmt_EBB (Char_literal (str.[lit_start], fmt))
+ | size -> Fmt_EBB (String_literal (String.sub str lit_start size, fmt))
+
+ (* Search the end of the current sub-format
+ (i.e. the corresponding "%}" or "%)") *)
+ and search_subformat_end str_ind end_ind c =
+ if str_ind = end_ind then
+ failwith_message
+ "invalid format %S: unclosed sub-format, \
+ expected \"%%%c\" at character number %d" str c end_ind;
+ match str.[str_ind] with
+ | '%' ->
+ if str_ind + 1 = end_ind then unexpected_end_of_format end_ind;
+ if str.[str_ind + 1] = c then (* End of format found *) str_ind else
+ begin match str.[str_ind + 1] with
+ | '_' ->
+ (* Search for "%_(" or "%_{". *)
+ if str_ind + 2 = end_ind then unexpected_end_of_format end_ind;
+ begin match str.[str_ind + 2] with
+ | '{' ->
+ let sub_end = search_subformat_end (str_ind + 3) end_ind '}' in
+ search_subformat_end (sub_end + 2) end_ind c
+ | '(' ->
+ let sub_end = search_subformat_end (str_ind + 3) end_ind ')' in
+ search_subformat_end (sub_end + 2) end_ind c
+ | _ -> search_subformat_end (str_ind + 3) end_ind c
+ end
+ | '{' ->
+ (* %{...%} sub-format found. *)
+ let sub_end = search_subformat_end (str_ind + 2) end_ind '}' in
+ search_subformat_end (sub_end + 2) end_ind c
+ | '(' ->
+ (* %(...%) sub-format found. *)
+ let sub_end = search_subformat_end (str_ind + 2) end_ind ')' in
+ search_subformat_end (sub_end + 2) end_ind c
+ | '}' ->
+ (* Error: %(...%}. *)
+ expected_character (str_ind + 1) "character ')'" '}';
+ | ')' ->
+ (* Error: %{...%). *)
+ expected_character (str_ind + 1) "character '}'" ')';
+ | _ ->
+ search_subformat_end (str_ind + 2) end_ind c
+ end
+ | _ -> search_subformat_end (str_ind + 1) end_ind c
+
+ (* Check if symb is a valid int conversion after "%l", "%n" or "%L" *)
+ and is_int_base symb = match symb with
+ | 'd' | 'i' | 'x' | 'X' | 'o' | 'u' -> true
+ | _ -> false
+
+ (* Convert a char (l, n or L) to its associated counter. *)
+ and counter_of_char symb = match symb with
+ | 'l' -> Line_counter | 'n' -> Char_counter
+ | 'L' -> Token_counter | _ -> assert false
+
+ (* Convert (plus, symb) to its associated int_conv. *)
+ and compute_int_conv pct_ind str_ind plus sharp space symb =
+ match plus, sharp, space, symb with
+ | false, false, false, 'd' -> Int_d | false, false, false, 'i' -> Int_i
+ | false, false, true, 'd' -> Int_sd | false, false, true, 'i' -> Int_si
+ | true, false, false, 'd' -> Int_pd | true, false, false, 'i' -> Int_pi
+ | false, false, false, 'x' -> Int_x | false, false, false, 'X' -> Int_X
+ | false, true, false, 'x' -> Int_Cx | false, true, false, 'X' -> Int_CX
+ | false, false, false, 'o' -> Int_o
+ | false, true, false, 'o' -> Int_Co
+ | false, false, false, 'u' -> Int_u
+ | _, true, _, 'x' when legacy_behavior -> Int_Cx
+ | _, true, _, 'X' when legacy_behavior -> Int_CX
+ | _, true, _, 'o' when legacy_behavior -> Int_Co
+ | _, true, _, _ ->
+ if legacy_behavior then (* ignore *)
+ compute_int_conv pct_ind str_ind plus false space symb
+ else incompatible_flag pct_ind str_ind symb "'#'"
+ | true, false, true, _ ->
+ if legacy_behavior then
+ (* plus and space: legacy implementation prefers plus *)
+ compute_int_conv pct_ind str_ind plus sharp false symb
+ else incompatible_flag pct_ind str_ind ' ' "'+'"
+ | false, false, true, _ ->
+ if legacy_behavior then (* ignore *)
+ compute_int_conv pct_ind str_ind plus sharp false symb
+ else incompatible_flag pct_ind str_ind symb "' '"
+ | true, false, false, _ ->
+ if legacy_behavior then (* ignore *)
+ compute_int_conv pct_ind str_ind false sharp space symb
+ else incompatible_flag pct_ind str_ind symb "'+'"
+ | false, false, false, _ -> assert false
+
+ (* Convert (plus, symb) to its associated float_conv. *)
+ and compute_float_conv pct_ind str_ind plus space symb =
+ match plus, space, symb with
+ | false, false, 'f' -> Float_f | false, false, 'e' -> Float_e
+ | false, true, 'f' -> Float_sf | false, true, 'e' -> Float_se
+ | true, false, 'f' -> Float_pf | true, false, 'e' -> Float_pe
+ | false, false, 'E' -> Float_E | false, false, 'g' -> Float_g
+ | false, true, 'E' -> Float_sE | false, true, 'g' -> Float_sg
+ | true, false, 'E' -> Float_pE | true, false, 'g' -> Float_pg
+ | false, false, 'G' -> Float_G
+ | false, true, 'G' -> Float_sG
+ | true, false, 'G' -> Float_pG
+ | false, false, 'F' -> Float_F
+ | true, true, _ ->
+ if legacy_behavior then
+ (* plus and space: legacy implementation prefers plus *)
+ compute_float_conv pct_ind str_ind plus false symb
+ else incompatible_flag pct_ind str_ind ' ' "'+'"
+ | false, true, _ ->
+ if legacy_behavior then (* ignore *)
+ compute_float_conv pct_ind str_ind plus false symb
+ else incompatible_flag pct_ind str_ind symb "' '"
+ | true, false, _ ->
+ if legacy_behavior then (* ignore *)
+ compute_float_conv pct_ind str_ind false space symb
+ else incompatible_flag pct_ind str_ind symb "'+'"
+ | false, false, _ -> assert false
+
+ (* Raise a Failure with a friendly error message about incompatible options.*)
+ and incompatible_flag : type a . int -> int -> char -> string -> a =
+ fun pct_ind str_ind symb option ->
+ let subfmt = String.sub str pct_ind (str_ind - pct_ind) in
+ failwith_message
+ "invalid format %S: at character number %d, \
+ %s is incompatible with '%c' in sub-format %S"
+ str pct_ind option symb subfmt;
+
+ in parse 0 (String.length str)
+
+(******************************************************************************)
+ (* Guarded string to format conversions *)
+
+(* Convert a string to a format according to an fmtty. *)
+(* Raise a Failure with an error message in case of type mismatch. *)
+let format_of_string_fmtty str fmtty =
+ let Fmt_EBB fmt = fmt_ebb_of_string str in
+ try Format (type_format fmt fmtty, str)
+ with Type_mismatch ->
+ failwith_message
+ "bad input: format type mismatch between %S and %S"
+ str (string_of_fmtty fmtty)
+
+(* Convert a string to a format compatible with an other format. *)
+(* Raise a Failure with an error message in case of type mismatch. *)
+let format_of_string_format str (Format (fmt', str')) =
+ let Fmt_EBB fmt = fmt_ebb_of_string str in
+ try Format (type_format fmt (fmtty_of_fmt fmt'), str)
+ with Type_mismatch ->
+ failwith_message
+ "bad input: format type mismatch between %S and %S" str str'
diff --git a/stdlib/camlinternalFormat.mli b/stdlib/camlinternalFormat.mli
new file mode 100644
index 0000000000..728dc865ac
--- /dev/null
+++ b/stdlib/camlinternalFormat.mli
@@ -0,0 +1,98 @@
+(* No comments, OCaml stdlib internal use only. *)
+
+open CamlinternalFormatBasics
+
+val is_in_char_set : char_set -> char -> bool
+val rev_char_set : char_set -> char_set
+
+type mutable_char_set = bytes
+val create_char_set : unit -> mutable_char_set
+val add_in_char_set : mutable_char_set -> char -> unit
+val freeze_char_set : mutable_char_set -> char_set
+
+type ('a, 'b, 'c, 'd, 'e, 'f) param_format_ebb = Param_format_EBB :
+ ('x -> 'a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) param_format_ebb
+
+val param_format_of_ignored_format :
+ ('a, 'b, 'c, 'd, 'y, 'x) ignored -> ('x, 'b, 'c, 'y, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) param_format_ebb
+
+type ('b, 'c) acc_formatting_gen =
+ | Acc_open_tag of ('b, 'c) acc
+ | Acc_open_box of ('b, 'c) acc
+
+and ('b, 'c) acc =
+ | Acc_formatting_lit of ('b, 'c) acc * formatting_lit
+ | Acc_formatting_gen of ('b, 'c) acc * ('b, 'c) acc_formatting_gen
+ | Acc_string of ('b, 'c) acc * string
+ | Acc_char of ('b, 'c) acc * char
+ | Acc_delay of ('b, 'c) acc * ('b -> 'c)
+ | Acc_flush of ('b, 'c) acc
+ | Acc_invalid_arg of ('b, 'c) acc * string
+ | End_of_acc
+
+type ('a, 'b) heter_list =
+ | Cons : 'c * ('a, 'b) heter_list -> ('c -> 'a, 'b) heter_list
+ | Nil : ('b, 'b) heter_list
+
+type ('b, 'c, 'e, 'f) fmt_ebb = Fmt_EBB :
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.fmt ->
+ ('b, 'c, 'e, 'f) fmt_ebb
+
+val make_printf :
+ ('b -> ('b, 'c) acc -> 'd) -> 'b -> ('b, 'c) acc ->
+ ('a, 'b, 'c, 'c, 'c, 'd) CamlinternalFormatBasics.fmt -> 'a
+
+val output_acc : out_channel -> (out_channel, unit) acc -> unit
+val bufput_acc : Buffer.t -> (Buffer.t, unit) acc -> unit
+val strput_acc : Buffer.t -> (unit, string) acc -> unit
+
+val type_format :
+ ('x, 'b, 'c, 't, 'u, 'v) CamlinternalFormatBasics.fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.fmtty ->
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.fmt
+
+val fmt_ebb_of_string : string -> ('b, 'c, 'e, 'f) fmt_ebb
+
+val format_of_string_fmtty :
+ string ->
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.fmtty ->
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.format6
+
+val format_of_string_format :
+ string ->
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.format6 ->
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.format6
+
+val char_of_iconv : CamlinternalFormatBasics.int_conv -> char
+val string_of_formatting_lit : CamlinternalFormatBasics.formatting_lit -> string
+val string_of_formatting_gen :
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.formatting_gen -> string
+
+val string_of_fmtty :
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.fmtty -> string
+val string_of_fmt :
+ ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.fmt -> string
+
+val open_box_of_string : string -> int * block_type
+
+val symm :
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+-> ('a2, 'b2, 'c2, 'd2, 'e2, 'f2,
+ 'a1, 'b1, 'c1, 'd1, 'e1, 'f1) fmtty_rel
+
+val trans :
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+-> ('a2, 'b2, 'c2, 'd2, 'e2, 'f2,
+ 'a3, 'b3, 'c3, 'd3, 'e3, 'f3) fmtty_rel
+-> ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a3, 'b3, 'c3, 'd3, 'e3, 'f3) fmtty_rel
+
+val recast :
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1) fmt
+-> ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+-> ('a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmt
diff --git a/stdlib/camlinternalFormatBasics.ml b/stdlib/camlinternalFormatBasics.ml
new file mode 100644
index 0000000000..e51e4e2ce8
--- /dev/null
+++ b/stdlib/camlinternalFormatBasics.ml
@@ -0,0 +1,614 @@
+(* Padding position. *)
+type padty =
+ | Left (* Text is left justified ('-' option). *)
+ | Right (* Text is right justified (no '-' option). *)
+ | Zeros (* Text is right justified by zeros (see '0' option). *)
+
+(***)
+
+(* Integer conversion. *)
+type int_conv =
+ | Int_d | Int_pd | Int_sd (* %d | %+d | % d *)
+ | Int_i | Int_pi | Int_si (* %i | %+i | % i *)
+ | Int_x | Int_Cx (* %x | %#x *)
+ | Int_X | Int_CX (* %X | %#X *)
+ | Int_o | Int_Co (* %o | %#o *)
+ | Int_u (* %u *)
+
+(* Float conversion. *)
+type float_conv =
+ | Float_f | Float_pf | Float_sf (* %f | %+f | % f *)
+ | Float_e | Float_pe | Float_se (* %e | %+e | % e *)
+ | Float_E | Float_pE | Float_sE (* %E | %+E | % E *)
+ | Float_g | Float_pg | Float_sg (* %g | %+g | % g *)
+ | Float_G | Float_pG | Float_sG (* %G | %+G | % G *)
+ | Float_F (* %F *)
+
+(***)
+
+(* Char sets (see %[...]) are bitmaps implemented as 32-char strings. *)
+type char_set = string
+
+(***)
+
+(* Counter used in Scanf. *)
+type counter =
+ | Line_counter (* %l *)
+ | Char_counter (* %n *)
+ | Token_counter (* %N, %L *)
+
+(***)
+
+(* Padding of strings and numbers. *)
+type ('a, 'b) padding =
+ (* No padding (ex: "%d") *)
+ | No_padding : ('a, 'a) padding
+ (* Literal padding (ex: "%8d") *)
+ | Lit_padding : padty * int -> ('a, 'a) padding
+ (* Padding as extra argument (ex: "%*d") *)
+ | Arg_padding : padty -> (int -> 'a, 'a) padding
+
+(* Some formats, such as %_d,
+ only accept an optional number as padding option (no extra argument) *)
+type pad_option = int option
+
+(* Precision of floats and '0'-padding of integers. *)
+type ('a, 'b) precision =
+ (* No precision (ex: "%f") *)
+ | No_precision : ('a, 'a) precision
+ (* Literal precision (ex: "%.3f") *)
+ | Lit_precision : int -> ('a, 'a) precision
+ (* Precision as extra argument (ex: "%.*f") *)
+ | Arg_precision : (int -> 'a, 'a) precision
+
+(* Some formats, such as %_f,
+ only accept an optional number as precision option (no extra argument) *)
+type prec_option = int option
+
+(***)
+
+(* Relational format types
+
+In the first format+gadts implementation, the type for %(..%) in the
+fmt GADT was as follows:
+
+| Format_subst : (* %(...%) *)
+ pad_option * ('d1, 'q1, 'd2, 'q2) reader_nb_unifier *
+ ('x, 'b, 'c, 'd1, 'q1, 'u) fmtty *
+ ('u, 'b, 'c, 'q1, 'e1, 'f) fmt ->
+ (('x, 'b, 'c, 'd2, 'q2, 'u) format6 -> 'x, 'b, 'c, 'd1, 'e1, 'f) fmt
+
+Notice that the 'u parameter in 'f position in the format argument
+(('x, .., 'u) format6 -> ..) is equal to the 'u parameter in 'a
+position in the format tail (('u, .., 'f) fmt). This means that the
+type of the expected format parameter depends of where the %(...%)
+are in the format string:
+
+ # Printf.printf "%(%)";;
+ - : (unit, out_channel, unit, '_a, '_a, unit)
+ CamlinternalFormatBasics.format6 -> unit
+ = <fun>
+ # Printf.printf "%(%)%d";;
+ - : (int -> unit, out_channel, unit, '_a, '_a, int -> unit)
+ CamlinternalFormatBasics.format6 -> int -> unit
+ = <fun>
+
+On the contrary, the legacy typer gives a clever type that does not
+depend on the position of %(..%) in the format string. For example,
+%(%) will have the polymorphic type ('a, 'b, 'c, 'd, 'd, 'a): it can
+be concatenated to any format type, and only enforces the constraint
+that its 'a and 'f parameters are equal (no format arguments) and 'd
+and 'e are equal (no reader argument).
+
+The weakening of this parameter type in the GADT version broke user
+code (in fact it essentially made %(...%) unusable except at the last
+position of a format). In particular, the following would not work
+anymore:
+
+ fun sep ->
+ Format.printf "foo%(%)bar%(%)baz" sep sep
+
+As the type-checker would require two *incompatible* types for the %(%)
+in different positions.
+
+The solution to regain a general type for %(..%) is to generalize this
+technique, not only on the 'd, 'e parameters, but on all six
+parameters of a format: we introduce a "relational" type
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+whose values are proofs that ('a1, .., 'f1) and ('a2, .., 'f2) morally
+correspond to the same format type: 'a1 is obtained from 'f1,'b1,'c1
+in the exact same way that 'a2 is obtained from 'f2,'b2,'c2, etc.
+
+For example, the relation between two format types beginning with a Char
+parameter is as follows:
+
+| Char_ty : (* %c *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (char -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ char -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+
+In the general case, the term structure of fmtty_rel is (almost¹)
+isomorphic to the fmtty of the previous implementation: every
+constructor is re-read with a binary, relational type, instead of the
+previous unary typing. fmtty can then be re-defined as the diagonal of
+fmtty_rel:
+
+ type ('a, 'b, 'c, 'd, 'e, 'f) fmtty =
+ ('a, 'b, 'c, 'd, 'e, 'f,
+ 'a, 'b, 'c, 'd, 'e, 'f) fmtty_rel
+
+Once we have this fmtty_rel type in place, we can give the more
+general type to %(...%):
+
+| Format_subst : (* %(...%) *)
+ pad_option *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b, 'c, 'j2, 'd, 'a) fmtty_rel *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b, 'c, 'j2, 'e, 'f) fmt
+
+We accept any format (('g, 'h, 'i, 'j, 'k, 'l) format6) (this is
+completely unrelated to the type of the current format), but also
+require a proof that this format is in relation to another format that
+is concatenable to the format tail. When executing a %(...%) format
+(in camlinternalFormat.ml:make_printf or scanf.ml:make_scanf), we
+transtype the format along this relation using the 'recast' function
+to transpose between related format types.
+
+ val recast :
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1) fmt
+ -> ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ -> ('a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmt
+
+NOTE ¹: the typing of Format_subst_ty requires not one format type, but
+two, one to establish the link between the format argument and the
+first six parameters, and the other for the link between the format
+argumant and the last six parameters.
+
+| Format_subst_ty : (* %(...%) *)
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g1, 'b1, 'c1, 'j1, 'd1, 'a1) fmtty_rel *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g1, 'b1, 'c1, 'j1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
+
+When we generate a format AST, we generate exactly the same witness
+for both relations, and the witness-conversion functions in
+camlinternalFormat do rely on this invariant. For example, the
+function that proves that the relation is transitive
+
+ val trans :
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ -> ('a2, 'b2, 'c2, 'd2, 'e2, 'f2,
+ 'a3, 'b3, 'c3, 'd3, 'e3, 'f3) fmtty_rel
+ -> ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a3, 'b3, 'c3, 'd3, 'e3, 'f3) fmtty_rel
+
+does assume that the two input have exactly the same term structure
+(and is only every used for argument witnesses of the
+Format_subst_ty constructor).
+*)
+
+(* Type of a block used by the Format pretty-printer. *)
+type block_type =
+ | Pp_hbox (* Horizontal block no line breaking *)
+ | Pp_vbox (* Vertical block each break leads to a new line *)
+ | Pp_hvbox (* Horizontal-vertical block: same as vbox, except if this block
+ is small enough to fit on a single line *)
+ | Pp_hovbox (* Horizontal or Vertical block: breaks lead to new line
+ only when necessary to print the content of the block *)
+ | Pp_box (* Horizontal or Indent block: breaks lead to new line
+ only when necessary to print the content of the block, or
+ when it leads to a new indentation of the current line *)
+ | Pp_fits (* Internal usage: when a block fits on a single line *)
+
+(* Formatting element used by the Format pretty-printter. *)
+type formatting_lit =
+ | Close_box (* @] *)
+ | Close_tag (* @} *)
+ | Break of string * int * int (* @, | @ | @; | @;<> *)
+ | FFlush (* @? *)
+ | Force_newline (* @\n *)
+ | Flush_newline (* @. *)
+ | Magic_size of string * int (* @<n> *)
+ | Escaped_at (* @@ *)
+ | Escaped_percent (* @%% *)
+ | Scan_indic of char (* @X *)
+
+(* Formatting element used by the Format pretty-printter. *)
+type ('a, 'b, 'c, 'd, 'e, 'f) formatting_gen =
+ | Open_tag : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> (* @{ *)
+ ('a, 'b, 'c, 'd, 'e, 'f) formatting_gen
+ | Open_box : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> (* @[ *)
+ ('a, 'b, 'c, 'd, 'e, 'f) formatting_gen
+
+(***)
+
+(* List of format type elements. *)
+(* In particular used to represent %(...%) and %{...%} contents. *)
+and ('a, 'b, 'c, 'd, 'e, 'f) fmtty =
+ ('a, 'b, 'c, 'd, 'e, 'f,
+ 'a, 'b, 'c, 'd, 'e, 'f) fmtty_rel
+and ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel =
+ | Char_ty : (* %c *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (char -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ char -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | String_ty : (* %s *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (string -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ string -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Int_ty : (* %d *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Int32_ty : (* %ld *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int32 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int32 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Nativeint_ty : (* %nd *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (nativeint -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ nativeint -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Int64_ty : (* %Ld *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int64 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int64 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Float_ty : (* %f *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (float -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ float -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Bool_ty : (* %B *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (bool -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ bool -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+
+ | Format_arg_ty : (* %{...%} *)
+ ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Format_subst_ty : (* %(...%) *)
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g1, 'b1, 'c1, 'j1, 'd1, 'a1) fmtty_rel *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g1, 'b1, 'c1, 'j1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
+
+ (* Printf and Format specific constructors. *)
+ | Alpha_ty : (* %a *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('b1 -> 'x -> 'c1) -> 'x -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('b2 -> 'x -> 'c2) -> 'x -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Theta_ty : (* %t *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('b1 -> 'c1) -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('b2 -> 'c2) -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+
+ (* Scanf specific constructor. *)
+ | Reader_ty : (* %r *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('x -> 'a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
+ 'x -> 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
+ | Ignored_reader_ty : (* %_r *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
+
+ | End_of_fmtty :
+ ('f1, 'b1, 'c1, 'd1, 'd1, 'f1,
+ 'f2, 'b2, 'c2, 'd2, 'd2, 'f2) fmtty_rel
+
+(***)
+
+(* List of format elements. *)
+and ('a, 'b, 'c, 'd, 'e, 'f) fmt =
+ | Char : (* %c *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Caml_char : (* %C *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | String : (* %s *)
+ ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Caml_string : (* %S *)
+ ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Int : (* %[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Int32 : (* %l[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int32 -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Nativeint : (* %n[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, nativeint -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Int64 : (* %L[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int64 -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Float : (* %[feEgGF] *)
+ float_conv * ('x, 'y) padding * ('y, float -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Bool : (* %[bB] *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (bool -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Flush : (* %! *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ | String_literal : (* abc *)
+ string * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Char_literal : (* x *)
+ char * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ | Format_arg : (* %{...%} *)
+ pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Format_subst : (* %(...%) *)
+ pad_option *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b, 'c, 'j2, 'd, 'a) fmtty_rel *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b, 'c, 'j2, 'e, 'f) fmt
+
+ (* Printf and Format specific constructor. *)
+ | Alpha : (* %a *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('b -> 'x -> 'c) -> 'x -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Theta : (* %t *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('b -> 'c) -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ (* Format specific constructor: *)
+ | Formatting_lit : (* @_ *)
+ formatting_lit * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Formatting_gen : (* @_ *)
+ ('a1, 'b, 'c, 'd1, 'e1, 'f1) formatting_gen *
+ ('f1, 'b, 'c, 'e1, 'e2, 'f2) fmt -> ('a1, 'b, 'c, 'd1, 'e2, 'f2) fmt
+
+ (* Scanf specific constructors: *)
+ | Reader : (* %r *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x -> 'a, 'b, 'c, ('b -> 'x) -> 'd, 'e, 'f) fmt
+ | Scan_char_set : (* %[...] *)
+ pad_option * char_set * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (string -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Scan_get_counter : (* %[nlNL] *)
+ counter * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (int -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Ignored_param : (* %_ *)
+ ('a, 'b, 'c, 'd, 'y, 'x) ignored * ('x, 'b, 'c, 'y, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ | End_of_format :
+ ('f, 'b, 'c, 'e, 'e, 'f) fmt
+
+(***)
+
+(* Type for ignored parameters (see "%_"). *)
+and ('a, 'b, 'c, 'd, 'e, 'f) ignored =
+ | Ignored_char : (* %_c *)
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_caml_char : (* %_C *)
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_string : (* %_s *)
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_caml_string : (* %_S *)
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int : (* %_d *)
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int32 : (* %_ld *)
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_nativeint : (* %_nd *)
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int64 : (* %_Ld *)
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_float : (* %_f *)
+ pad_option * prec_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_bool : (* %_B *)
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_format_arg : (* %_{...%} *)
+ pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty ->
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_format_subst : (* %_(...%) *)
+ pad_option * ('a, 'b, 'c, 'd, 'e, 'f) fmtty ->
+ ('a, 'b, 'c, 'd, 'e, 'f) ignored
+ | Ignored_reader : (* %_r *)
+ ('a, 'b, 'c, ('b -> 'x) -> 'd, 'd, 'a) ignored
+ | Ignored_scan_char_set : (* %_[...] *)
+ pad_option * char_set -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_scan_get_counter : (* %_[nlNL] *)
+ counter -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+
+and ('a, 'b, 'c, 'd, 'e, 'f) format6 =
+ Format of ('a, 'b, 'c, 'd, 'e, 'f) fmt * string
+
+let rec erase_rel : type a b c d e f g h i j k l .
+ (a, b, c, d, e, f,
+ g, h, i, j, k, l) fmtty_rel -> (a, b, c, d, e, f) fmtty
+= function
+ | Char_ty rest ->
+ Char_ty (erase_rel rest)
+ | String_ty rest ->
+ String_ty (erase_rel rest)
+ | Int_ty rest ->
+ Int_ty (erase_rel rest)
+ | Int32_ty rest ->
+ Int32_ty (erase_rel rest)
+ | Int64_ty rest ->
+ Int64_ty (erase_rel rest)
+ | Nativeint_ty rest ->
+ Nativeint_ty (erase_rel rest)
+ | Float_ty rest ->
+ Float_ty (erase_rel rest)
+ | Bool_ty rest ->
+ Bool_ty (erase_rel rest)
+ | Format_arg_ty (ty, rest) ->
+ Format_arg_ty (ty, erase_rel rest)
+ | Format_subst_ty (ty1, ty2, rest) ->
+ Format_subst_ty (ty1, ty1, erase_rel rest)
+ | Alpha_ty rest ->
+ Alpha_ty (erase_rel rest)
+ | Theta_ty rest ->
+ Theta_ty (erase_rel rest)
+ | Reader_ty rest ->
+ Reader_ty (erase_rel rest)
+ | Ignored_reader_ty rest ->
+ Ignored_reader_ty (erase_rel rest)
+ | End_of_fmtty -> End_of_fmtty
+
+(******************************************************************************)
+ (* Format type concatenation *)
+
+(* Concatenate two format types. *)
+(* Used by:
+ * reader_nb_unifier_of_fmtty to count readers in an fmtty,
+ * Scanf.take_fmtty_format_readers to extract readers inside %(...%),
+ * CamlinternalFormat.fmtty_of_ignored_format to extract format type. *)
+
+(*
+let rec concat_fmtty : type a b c d e f g h .
+ (a, b, c, d, e, f) fmtty ->
+ (f, b, c, e, g, h) fmtty ->
+ (a, b, c, d, g, h) fmtty =
+*)
+let rec concat_fmtty :
+ type a1 b1 c1 d1 e1 f1
+ a2 b2 c2 d2 e2 f2
+ g1 j1 g2 j2
+ .
+ (g1, b1, c1, j1, d1, a1,
+ g2, b2, c2, j2, d2, a2) fmtty_rel ->
+ (a1, b1, c1, d1, e1, f1,
+ a2, b2, c2, d2, e2, f2) fmtty_rel ->
+ (g1, b1, c1, j1, e1, f1,
+ g2, b2, c2, j2, e2, f2) fmtty_rel =
+fun fmtty1 fmtty2 -> match fmtty1 with
+ | Char_ty rest ->
+ Char_ty (concat_fmtty rest fmtty2)
+ | String_ty rest ->
+ String_ty (concat_fmtty rest fmtty2)
+ | Int_ty rest ->
+ Int_ty (concat_fmtty rest fmtty2)
+ | Int32_ty rest ->
+ Int32_ty (concat_fmtty rest fmtty2)
+ | Nativeint_ty rest ->
+ Nativeint_ty (concat_fmtty rest fmtty2)
+ | Int64_ty rest ->
+ Int64_ty (concat_fmtty rest fmtty2)
+ | Float_ty rest ->
+ Float_ty (concat_fmtty rest fmtty2)
+ | Bool_ty rest ->
+ Bool_ty (concat_fmtty rest fmtty2)
+ | Alpha_ty rest ->
+ Alpha_ty (concat_fmtty rest fmtty2)
+ | Theta_ty rest ->
+ Theta_ty (concat_fmtty rest fmtty2)
+ | Reader_ty rest ->
+ Reader_ty (concat_fmtty rest fmtty2)
+ | Ignored_reader_ty rest ->
+ Ignored_reader_ty (concat_fmtty rest fmtty2)
+ | Format_arg_ty (ty, rest) ->
+ Format_arg_ty (ty, concat_fmtty rest fmtty2)
+ | Format_subst_ty (ty1, ty2, rest) ->
+ Format_subst_ty (ty1, ty2, concat_fmtty rest fmtty2)
+ | End_of_fmtty -> fmtty2
+
+(******************************************************************************)
+ (* Format concatenation *)
+
+(* Concatenate two formats. *)
+let rec concat_fmt : type a b c d e f g h .
+ (a, b, c, d, e, f) fmt ->
+ (f, b, c, e, g, h) fmt ->
+ (a, b, c, d, g, h) fmt =
+fun fmt1 fmt2 -> match fmt1 with
+ | String (pad, rest) ->
+ String (pad, concat_fmt rest fmt2)
+ | Caml_string (pad, rest) ->
+ Caml_string (pad, concat_fmt rest fmt2)
+
+ | Int (iconv, pad, prec, rest) ->
+ Int (iconv, pad, prec, concat_fmt rest fmt2)
+ | Int32 (iconv, pad, prec, rest) ->
+ Int32 (iconv, pad, prec, concat_fmt rest fmt2)
+ | Nativeint (iconv, pad, prec, rest) ->
+ Nativeint (iconv, pad, prec, concat_fmt rest fmt2)
+ | Int64 (iconv, pad, prec, rest) ->
+ Int64 (iconv, pad, prec, concat_fmt rest fmt2)
+ | Float (fconv, pad, prec, rest) ->
+ Float (fconv, pad, prec, concat_fmt rest fmt2)
+
+ | Char (rest) ->
+ Char (concat_fmt rest fmt2)
+ | Caml_char rest ->
+ Caml_char (concat_fmt rest fmt2)
+ | Bool rest ->
+ Bool (concat_fmt rest fmt2)
+ | Alpha rest ->
+ Alpha (concat_fmt rest fmt2)
+ | Theta rest ->
+ Theta (concat_fmt rest fmt2)
+ | Reader rest ->
+ Reader (concat_fmt rest fmt2)
+ | Flush rest ->
+ Flush (concat_fmt rest fmt2)
+
+ | String_literal (str, rest) ->
+ String_literal (str, concat_fmt rest fmt2)
+ | Char_literal (chr, rest) ->
+ Char_literal (chr, concat_fmt rest fmt2)
+
+ | Format_arg (pad, fmtty, rest) ->
+ Format_arg (pad, fmtty, concat_fmt rest fmt2)
+ | Format_subst (pad, fmtty, rest) ->
+ Format_subst (pad, fmtty, concat_fmt rest fmt2)
+
+ | Scan_char_set (width_opt, char_set, rest) ->
+ Scan_char_set (width_opt, char_set, concat_fmt rest fmt2)
+ | Scan_get_counter (counter, rest) ->
+ Scan_get_counter (counter, concat_fmt rest fmt2)
+ | Ignored_param (ign, rest) ->
+ Ignored_param (ign, concat_fmt rest fmt2)
+
+ | Formatting_lit (fmting_lit, rest) ->
+ Formatting_lit (fmting_lit, concat_fmt rest fmt2)
+ | Formatting_gen (fmting_gen, rest) ->
+ Formatting_gen (fmting_gen, concat_fmt rest fmt2)
+
+ | End_of_format ->
+ fmt2
diff --git a/stdlib/camlinternalFormatBasics.mli b/stdlib/camlinternalFormatBasics.mli
new file mode 100644
index 0000000000..52f428ad83
--- /dev/null
+++ b/stdlib/camlinternalFormatBasics.mli
@@ -0,0 +1,287 @@
+(* No comments, OCaml stdlib internal use only. *)
+
+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
+
+type float_conv =
+ | Float_f | Float_pf | Float_sf | Float_e | Float_pe | Float_se
+ | Float_E | Float_pE | Float_sE | Float_g | Float_pg | Float_sg
+ | Float_G | Float_pG | Float_sG | Float_F
+
+type char_set = string
+
+type counter = Line_counter | Char_counter | Token_counter
+
+type ('a, 'b) padding =
+ | No_padding : ('a, 'a) padding
+ | Lit_padding : padty * int -> ('a, 'a) padding
+ | Arg_padding : padty -> (int -> 'a, 'a) padding
+
+type pad_option = int option
+
+type ('a, 'b) precision =
+ | No_precision : ('a, 'a) precision
+ | Lit_precision : int -> ('a, 'a) precision
+ | Arg_precision : (int -> 'a, 'a) precision
+
+type prec_option = int option
+
+type block_type = Pp_hbox | Pp_vbox | Pp_hvbox | Pp_hovbox | Pp_box | Pp_fits
+
+type formatting_lit =
+ | Close_box
+ | Close_tag
+ | Break of string * int * int
+ | FFlush
+ | Force_newline
+ | Flush_newline
+ | Magic_size of string * int
+ | Escaped_at
+ | Escaped_percent
+ | Scan_indic of char
+
+type ('a, 'b, 'c, 'd, 'e, 'f) formatting_gen =
+ | Open_tag : ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
+ ('a, 'b, 'c, 'd, 'e, 'f) formatting_gen
+ | Open_box : ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
+ ('a, 'b, 'c, 'd, 'e, 'f) formatting_gen
+
+and ('a, 'b, 'c, 'd, 'e, 'f) fmtty =
+ ('a, 'b, 'c, 'd, 'e, 'f,
+ 'a, 'b, 'c, 'd, 'e, 'f) fmtty_rel
+and ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel =
+| Char_ty : (* %c *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (char -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ char -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| String_ty : (* %s *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (string -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ string -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| Int_ty : (* %d *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| Int32_ty : (* %ld *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int32 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int32 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| Nativeint_ty : (* %nd *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (nativeint -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ nativeint -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| Int64_ty : (* %Ld *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int64 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int64 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| Float_ty : (* %f *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (float -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ float -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| Bool_ty : (* %B *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (bool -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ bool -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| Format_arg_ty : (* %{...%} *)
+ ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| Format_subst_ty : (* %(...%) *)
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g1, 'b1, 'c1, 'j1, 'd1, 'a1) fmtty_rel *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g1, 'b1, 'c1, 'j1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
+
+(* Printf and Format specific constructors. *)
+| Alpha_ty : (* %a *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('b1 -> 'x -> 'c1) -> 'x -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('b2 -> 'x -> 'c2) -> 'x -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+| Theta_ty : (* %t *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('b1 -> 'c1) -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('b2 -> 'c2) -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+
+(* Scanf specific constructor. *)
+| Reader_ty : (* %r *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('x -> 'a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
+ 'x -> 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
+| Ignored_reader_ty : (* %_r *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
+
+| End_of_fmtty :
+ ('f1, 'b1, 'c1, 'd1, 'd1, 'f1,
+ 'f2, 'b2, 'c2, 'd2, 'd2, 'f2) fmtty_rel
+
+(**)
+
+(** List of format elements. *)
+and ('a, 'b, 'c, 'd, 'e, 'f) fmt =
+| Char : (* %c *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+| Caml_char : (* %C *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+| String : (* %s *)
+ ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+| Caml_string : (* %S *)
+ ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+| Int : (* %[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+| Int32 : (* %l[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int32 -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+| Nativeint : (* %n[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, nativeint -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+| Int64 : (* %L[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int64 -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+| Float : (* %[feEgGF] *)
+ float_conv * ('x, 'y) padding * ('y, float -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+| Bool : (* %[bB] *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (bool -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+| Flush : (* %! *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+| String_literal : (* abc *)
+ string * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+| Char_literal : (* x *)
+ char * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+| Format_arg : (* %{...%} *)
+ pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+| Format_subst : (* %(...%) *)
+ pad_option *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b, 'c, 'j2, 'd, 'a) fmtty_rel *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b, 'c, 'j2, 'e, 'f) fmt
+
+(* Printf and Format specific constructor. *)
+| Alpha : (* %a *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('b -> 'x -> 'c) -> 'x -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+| Theta : (* %t *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('b -> 'c) -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+
+(* Format specific constructor: *)
+| Formatting_lit : (* @_ *)
+ formatting_lit * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+| Formatting_gen : (* @_ *)
+ ('a1, 'b, 'c, 'd1, 'e1, 'f1) formatting_gen *
+ ('f1, 'b, 'c, 'e1, 'e2, 'f2) fmt -> ('a1, 'b, 'c, 'd1, 'e2, 'f2) fmt
+
+(* Scanf specific constructors: *)
+| Reader : (* %r *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x -> 'a, 'b, 'c, ('b -> 'x) -> 'd, 'e, 'f) fmt
+| Scan_char_set : (* %[...] *)
+ pad_option * char_set * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (string -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+| Scan_get_counter : (* %[nlNL] *)
+ counter * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (int -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+| Ignored_param : (* %_ *)
+ ('a, 'b, 'c, 'd, 'y, 'x) ignored * ('x, 'b, 'c, 'y, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+| End_of_format :
+ ('f, 'b, 'c, 'e, 'e, 'f) fmt
+
+and ('a, 'b, 'c, 'd, 'e, 'f) ignored =
+ | Ignored_char :
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_caml_char :
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_string :
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_caml_string :
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int :
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int32 :
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_nativeint :
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int64 :
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_float :
+ pad_option * prec_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_bool :
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_format_arg :
+ pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty ->
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_format_subst :
+ pad_option * ('a, 'b, 'c, 'd, 'e, 'f) fmtty ->
+ ('a, 'b, 'c, 'd, 'e, 'f) ignored
+ | Ignored_reader :
+ ('a, 'b, 'c, ('b -> 'x) -> 'd, 'd, 'a) ignored
+ | Ignored_scan_char_set :
+ pad_option * char_set -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_scan_get_counter :
+ counter -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+
+and ('a, 'b, 'c, 'd, 'e, 'f) format6 =
+ Format of ('a, 'b, 'c, 'd, 'e, 'f) fmt * string
+
+val concat_fmtty :
+ ('g1, 'b1, 'c1, 'j1, 'd1, 'a1,
+ 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel ->
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('g1, 'b1, 'c1, 'j1, 'e1, 'f1,
+ 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
+
+val erase_rel :
+ ('a, 'b, 'c, 'd, 'e, 'f,
+ 'g, 'h, 'i, 'j, 'k, 'l) fmtty_rel -> ('a, 'b, 'c, 'd, 'e, 'f) fmtty
+
+val concat_fmt :
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('f, 'b, 'c, 'e, 'g, 'h) fmt ->
+ ('a, 'b, 'c, 'd, 'g, 'h) fmt
diff --git a/stdlib/digest.ml b/stdlib/digest.ml
index 7c607ee1f8..14cb4ebd90 100644
--- a/stdlib/digest.ml
+++ b/stdlib/digest.ml
@@ -23,11 +23,15 @@ external channel: in_channel -> int -> t = "caml_md5_chan"
let string str =
unsafe_string str 0 (String.length str)
+let bytes b = string (Bytes.unsafe_to_string b)
+
let substring str ofs len =
if ofs < 0 || len < 0 || ofs > String.length str - len
then invalid_arg "Digest.substring"
else unsafe_string str ofs len
+let subbytes b ofs len = substring (Bytes.unsafe_to_string b) ofs len
+
let file filename =
let ic = open_in_bin filename in
let d = channel ic (-1) in
@@ -35,24 +39,21 @@ let file filename =
d
let output chan digest =
- output chan digest 0 16
+ output_string chan digest
-let input chan =
- let digest = String.create 16 in
- really_input chan digest 0 16;
- digest
+let input chan = really_input_string chan 16
let char_hex n =
Char.unsafe_chr (n + if n < 10 then Char.code '0' else (Char.code 'a' - 10))
let to_hex d =
- let result = String.create 32 in
+ let result = Bytes.create 32 in
for i = 0 to 15 do
let x = Char.code d.[i] in
- String.unsafe_set result (i*2) (char_hex (x lsr 4));
- String.unsafe_set result (i*2+1) (char_hex (x land 0x0f));
+ Bytes.unsafe_set result (i*2) (char_hex (x lsr 4));
+ Bytes.unsafe_set result (i*2+1) (char_hex (x land 0x0f));
done;
- result
+ Bytes.unsafe_to_string result
let from_hex s =
if String.length s <> 32 then raise (Invalid_argument "Digest.from_hex");
@@ -64,8 +65,8 @@ let from_hex s =
| _ -> raise (Invalid_argument "Digest.from_hex")
in
let byte i = digit s.[i] lsl 4 + digit s.[i+1] in
- let result = String.create 16 in
+ let result = Bytes.create 16 in
for i = 0 to 15 do
- result.[i] <- Char.chr (byte (2 * i));
+ Bytes.set result i (Char.chr (byte (2 * i)));
done;
- result
+ Bytes.unsafe_to_string result
diff --git a/stdlib/digest.mli b/stdlib/digest.mli
index 7fa1f15d62..583d2a46b0 100644
--- a/stdlib/digest.mli
+++ b/stdlib/digest.mli
@@ -36,10 +36,16 @@ val compare : t -> t -> int
val string : string -> t
(** Return the digest of the given string. *)
+val bytes : bytes -> t
+(** Return the digest of the given byte sequence. *)
+
val substring : string -> int -> int -> t
(** [Digest.substring s ofs len] returns the digest of the substring
- of [s] starting at character number [ofs] and containing [len]
- characters. *)
+ of [s] starting at index [ofs] and containing [len] characters. *)
+
+val subbytes : bytes -> int -> int -> t
+(** [Digest.subbytes s ofs len] returns the digest of the subsequence
+ of [s] starting at index [ofs] and containing [len] bytes. *)
external channel : in_channel -> int -> t = "caml_md5_chan"
(** If [len] is nonnegative, [Digest.channel ic len] reads [len]
diff --git a/stdlib/format.ml b/stdlib/format.ml
index 02222932e4..55674d179b 100644
--- a/stdlib/format.ml
+++ b/stdlib/format.ml
@@ -29,6 +29,10 @@ external int_of_size : size -> int = "%identity"
(* Tokens are one of the following : *)
+type block_type
+ = CamlinternalFormatBasics.block_type
+ = Pp_hbox | Pp_vbox | Pp_hvbox | Pp_hovbox | Pp_box | Pp_fits
+
type pp_token =
| Pp_text of string (* normal text *)
| Pp_break of int * int (* complete break *)
@@ -46,21 +50,7 @@ type pp_token =
and tag = string
-and block_type =
-| Pp_hbox (* Horizontal block no line breaking *)
-| Pp_vbox (* Vertical block each break leads to a new line *)
-| Pp_hvbox (* Horizontal-vertical block: same as vbox, except if this block
- is small enough to fit on a single line *)
-| Pp_hovbox (* Horizontal or Vertical block: breaks lead to new line
- only when necessary to print the content of the block *)
-| Pp_box (* Horizontal or Indent block: breaks lead to new line
- only when necessary to print the content of the block, or
- when it leads to a new indentation of the current line *)
-| Pp_fits (* Internal usage: when a block fits on a single line *)
-
-and tblock =
- | Pp_tbox of int list ref (* Tabulation box *)
-;;
+and tblock = Pp_tbox of int list ref (* Tabulation box *)
(* The Queue:
contains all formatting elements.
@@ -241,7 +231,6 @@ let pp_infinity = 1000000010;;
let pp_output_string state s = state.pp_out_string s 0 (String.length s)
and pp_output_newline state = state.pp_out_newline ()
and pp_output_spaces state n = state.pp_out_spaces n
-;;
(* To format a break, indenting a new line. *)
let break_new_line state offset width =
@@ -657,9 +646,7 @@ let pp_print_bool state b = pp_print_string state (string_of_bool b);;
(* To format a char. *)
let pp_print_char state c =
- let s = String.create 1 in
- s.[0] <- c;
- pp_print_as state 1 s
+ pp_print_as state 1 (String.make 1 c)
;;
(* Opening boxes. *)
@@ -901,7 +888,7 @@ let rec display_blanks state n =
;;
let pp_set_formatter_out_channel state os =
- state.pp_out_string <- output os;
+ state.pp_out_string <- output_substring os;
state.pp_out_flush <- (fun () -> flush os);
state.pp_out_newline <- display_newline state;
state.pp_out_spaces <- display_blanks state;
@@ -967,7 +954,7 @@ let make_formatter output flush =
;;
let formatter_of_out_channel oc =
- make_formatter (output oc) (fun () -> flush oc)
+ make_formatter (output_substring oc) (fun () -> flush oc)
;;
let formatter_of_buffer b =
@@ -1071,309 +1058,98 @@ and set_tags =
pp_set_tags std_formatter
;;
-
-(**************************************************************
-
- Printf implementation.
-
- **************************************************************)
-
-module Sformat = Printf.CamlinternalPr.Sformat;;
-module Tformat = Printf.CamlinternalPr.Tformat;;
-
-(* Error messages when processing formats. *)
-
-(* Trailer: giving up at character number ... *)
-let giving_up mess fmt i =
- Printf.sprintf
- "Format.fprintf: %s \'%s\', giving up at character number %d%s"
- mess (Sformat.to_string fmt) i
- (if i < Sformat.length fmt
- then Printf.sprintf " (%c)." (Sformat.get fmt i)
- else Printf.sprintf "%c" '.')
-;;
-
-(* When an invalid format deserves a special error explanation. *)
-let format_invalid_arg mess fmt i = invalid_arg (giving_up mess fmt i);;
-
-(* Standard invalid format. *)
-let invalid_format fmt i = format_invalid_arg "bad format" fmt i;;
-
-(* Cannot find a valid integer into that format. *)
-let invalid_integer fmt i =
- invalid_arg (giving_up "bad integer specification" fmt i);;
-
-(* Finding an integer size out of a sub-string of the format. *)
-let format_int_of_string fmt i s =
- let sz =
- try int_of_string s with
- | Failure _ -> invalid_integer fmt i in
- size_of_int sz
-;;
-
-(* Getting strings out of buffers. *)
-let get_buffer_out b =
- let s = Buffer.contents b in
- Buffer.reset b;
- s
-;;
-
-(* [ppf] is supposed to be a pretty-printer that outputs to buffer [b]:
- to extract the contents of [ppf] as a string we flush [ppf] and get the
- string out of [b]. *)
-let string_out b ppf =
- pp_flush_queue ppf false;
- get_buffer_out b
-;;
-
-(* Applies [printer] to a formatter that outputs on a fresh buffer,
- then returns the resulting material. *)
-let exstring printer arg =
- let b = Buffer.create 512 in
- let ppf = formatter_of_buffer b in
- printer ppf arg;
- string_out b ppf
-;;
-
-(* To turn out a character accumulator into the proper string result. *)
-let implode_rev s0 = function
- | [] -> s0
- | l -> String.concat "" (List.rev (s0 :: l))
-;;
-
-(* [mkprintf] is the printf-like function generator: given the
- - [to_s] flag that tells if we are printing into a string,
- - the [get_out] function that has to be called to get a [ppf] function to
- output onto,
- it generates a [kprintf] function that takes as arguments a [k]
- continuation function to be called at the end of formatting,
- and a printing format string to print the rest of the arguments
- according to the format string.
- Regular [fprintf]-like functions of this module are obtained via partial
- applications of [mkprintf]. *)
-let mkprintf to_s get_out k fmt =
-
- (* [out] is global to this definition of [pr], and must be shared by all its
- recursive calls (if any). *)
- let out = get_out fmt in
- let print_as = ref None in
- let outc c =
- match !print_as with
- | None -> pp_print_char out c
- | Some size ->
- pp_print_as_size out size (String.make 1 c);
- print_as := None
- and outs s =
- match !print_as with
- | None -> pp_print_string out s
- | Some size ->
- pp_print_as_size out size s;
- print_as := None
- and flush out = pp_print_flush out () in
-
- let rec pr k n fmt v =
-
- let len = Sformat.length fmt in
-
- let rec doprn n i =
- if i >= len then Obj.magic (k out) else
- match Sformat.get fmt i with
- | '%' ->
- Tformat.scan_format fmt v n i cont_s cont_a cont_t cont_f cont_m
- | '@' ->
- let i = succ i in
- if i >= len then invalid_format fmt i else
- begin match Sformat.get fmt i with
- | '[' ->
- do_pp_open_box out n (succ i)
- | ']' ->
- pp_close_box out ();
- doprn n (succ i)
- | '{' ->
- do_pp_open_tag out n (succ i)
- | '}' ->
- pp_close_tag out ();
- doprn n (succ i)
- | ' ' ->
- pp_print_space out ();
- doprn n (succ i)
- | ',' ->
- pp_print_cut out ();
- doprn n (succ i)
- | '?' ->
- pp_print_flush out ();
- doprn n (succ i)
- | '.' ->
- pp_print_newline out ();
- doprn n (succ i)
- | '\n' ->
- pp_force_newline out ();
- doprn n (succ i)
- | ';' ->
- do_pp_break out n (succ i)
- | '<' ->
- let got_size size n i =
- print_as := Some size;
- doprn n (skip_gt i) in
- get_int n (succ i) got_size
- | '@' ->
- outc '@';
- doprn n (succ i)
- | _ -> invalid_format fmt i
- end
- | c -> outc c; doprn n (succ i)
-
- and cont_s n s i =
- outs s; doprn n i
- and cont_a n printer arg i =
- if to_s then
- outs ((Obj.magic printer : unit -> _ -> string) () arg)
- else
- printer out arg;
- doprn n i
- and cont_t n printer i =
- if to_s then
- outs ((Obj.magic printer : unit -> string) ())
- else
- printer out;
- doprn n i
- and cont_f n i =
- flush out; doprn n i
- and cont_m n xf i =
- let m =
- Sformat.add_int_index
- (Tformat.count_printing_arguments_of_format xf) n in
- pr (Obj.magic (fun _ -> doprn m i)) n xf v
-
- and get_int n i c =
- if i >= len then invalid_integer fmt i else
- match Sformat.get fmt i with
- | ' ' -> get_int n (succ i) c
- | '%' ->
- let cont_s n s i = c (format_int_of_string fmt i s) n i
- and cont_a _n _printer _arg i = invalid_integer fmt i
- and cont_t _n _printer i = invalid_integer fmt i
- and cont_f _n i = invalid_integer fmt i
- and cont_m _n _sfmt i = invalid_integer fmt i in
- Tformat.scan_format fmt v n i cont_s cont_a cont_t cont_f cont_m
- | _ ->
- let rec get j =
- if j >= len then invalid_integer fmt j else
- match Sformat.get fmt j with
- | '0' .. '9' | '-' -> get (succ j)
- | _ ->
- let size =
- if j = i then size_of_int 0 else
- let s = Sformat.sub fmt (Sformat.index_of_int i) (j - i) in
- format_int_of_string fmt j s in
- c size n j in
- get i
-
- and skip_gt i =
- if i >= len then invalid_format fmt i else
- match Sformat.get fmt i with
- | ' ' -> skip_gt (succ i)
- | '>' -> succ i
- | _ -> invalid_format fmt i
-
- and get_box_kind i =
- if i >= len then Pp_box, i else
- match Sformat.get fmt i with
- | 'h' ->
- let i = succ i in
- if i >= len then Pp_hbox, i else
- begin match Sformat.get fmt i with
- | 'o' ->
- let i = succ i in
- if i >= len then format_invalid_arg "bad box format" fmt i else
- begin match Sformat.get fmt i with
- | 'v' -> Pp_hovbox, succ i
- | c ->
- format_invalid_arg
- ("bad box name ho" ^ String.make 1 c) fmt i
- end
- | 'v' -> Pp_hvbox, succ i
- | _ -> Pp_hbox, i
- end
- | 'b' -> Pp_box, succ i
- | 'v' -> Pp_vbox, succ i
- | _ -> Pp_box, i
-
- and get_tag_name n i c =
- let rec get accu n i j =
- if j >= len then
- c (implode_rev
- (Sformat.sub fmt (Sformat.index_of_int i) (j - i))
- accu)
- n j else
- match Sformat.get fmt j with
- | '>' ->
- c (implode_rev
- (Sformat.sub fmt (Sformat.index_of_int i) (j - i))
- accu)
- n j
- | '%' ->
- let s0 = Sformat.sub fmt (Sformat.index_of_int i) (j - i) in
- let cont_s n s i = get (s :: s0 :: accu) n i i
- and cont_a n printer arg i =
- let s =
- if to_s
- then (Obj.magic printer : unit -> _ -> string) () arg
- else exstring printer arg in
- get (s :: s0 :: accu) n i i
- and cont_t n printer i =
- let s =
- if to_s
- then (Obj.magic printer : unit -> string) ()
- else exstring (fun ppf () -> printer ppf) () in
- get (s :: s0 :: accu) n i i
- and cont_f _n i =
- format_invalid_arg "bad tag name specification" fmt i
- and cont_m _n _sfmt i =
- format_invalid_arg "bad tag name specification" fmt i in
- Tformat.scan_format fmt v n j cont_s cont_a cont_t cont_f cont_m
- | _ -> get accu n i (succ j) in
- get [] n i i
-
- and do_pp_break ppf n i =
- if i >= len then begin pp_print_space ppf (); doprn n i end else
- match Sformat.get fmt i with
- | '<' ->
- let rec got_nspaces nspaces n i =
- get_int n i (got_offset nspaces)
- and got_offset nspaces offset n i =
- pp_print_break ppf (int_of_size nspaces) (int_of_size offset);
- doprn n (skip_gt i) in
- get_int n (succ i) got_nspaces
- | _c -> pp_print_space ppf (); doprn n i
-
- and do_pp_open_box ppf n i =
- if i >= len then begin pp_open_box_gen ppf 0 Pp_box; doprn n i end else
- match Sformat.get fmt i with
- | '<' ->
- let kind, i = get_box_kind (succ i) in
- let got_size size n i =
- pp_open_box_gen ppf (int_of_size size) kind;
- doprn n (skip_gt i) in
- get_int n i got_size
- | _c -> pp_open_box_gen ppf 0 Pp_box; doprn n i
-
- and do_pp_open_tag ppf n i =
- if i >= len then begin pp_open_tag ppf ""; doprn n i end else
- match Sformat.get fmt i with
- | '<' ->
- let got_name tag_name n i =
- pp_open_tag ppf tag_name;
- doprn n (skip_gt i) in
- get_tag_name n (succ i) got_name
- | _c -> pp_open_tag ppf ""; doprn n i in
-
- doprn n 0 in
-
- let kpr = pr k (Sformat.index_of_int 0) in
-
- Tformat.kapr kpr fmt
-;;
+ (**************************************************************)
+
+let compute_tag output tag_acc =
+ let buf = Buffer.create 16 in
+ let ppf = formatter_of_buffer buf in
+ let () = output ppf tag_acc in
+ let () = pp_print_flush ppf () in
+ let len = Buffer.length buf in
+ if len < 2 then Buffer.contents buf
+ else Buffer.sub buf 1 (len - 2)
+
+ (**************************************************************
+
+ Defining continuations to be passed as arguments of
+ CamlinternalFormat.make_printf.
+
+ **************************************************************)
+
+open CamlinternalFormatBasics
+open CamlinternalFormat
+
+(* Interpret a formatting entity on a formatter. *)
+let output_formatting_lit ppf fmting_lit = match fmting_lit with
+ | Close_box -> pp_close_box ppf ()
+ | Close_tag -> pp_close_tag ppf ()
+ | Break (_, width, offset) -> pp_print_break ppf width offset
+ | FFlush -> pp_print_flush ppf ()
+ | Force_newline -> pp_force_newline ppf ()
+ | Flush_newline -> pp_print_newline ppf ()
+ | Magic_size (_, _) -> ()
+ | Escaped_at -> pp_print_char ppf '@'
+ | Escaped_percent -> pp_print_char ppf '%'
+ | Scan_indic c -> pp_print_char ppf '@'; pp_print_char ppf c
+
+(* Recursively output an "accumulator" containing a reversed list of
+ printing entities (string, char, flus, ...) in an output_stream. *)
+(* Differ from Printf.output_acc by the interpretation of formatting. *)
+(* Used as a continuation of CamlinternalFormat.make_printf. *)
+let rec output_acc ppf acc = match acc with
+ | Acc_string (Acc_formatting_lit (p, Magic_size (_, size)), s) ->
+ output_acc ppf p;
+ pp_print_as_size ppf (size_of_int size) s;
+ | Acc_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);
+ | 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')
+ | Acc_formatting_gen (p, Acc_open_box acc') ->
+ let () = output_acc ppf p in
+ let (indent, bty) = open_box_of_string (compute_tag output_acc acc') in
+ pp_open_box_gen ppf indent bty
+ | Acc_string (p, s) -> output_acc ppf p; pp_print_string ppf s;
+ | Acc_char (p, c) -> output_acc ppf p; pp_print_char ppf c;
+ | Acc_delay (p, f) -> output_acc ppf p; f ppf;
+ | Acc_flush p -> output_acc ppf p; pp_print_flush ppf ();
+ | Acc_invalid_arg (p, msg) -> output_acc ppf p; invalid_arg msg;
+ | End_of_acc -> ()
+
+(* Recursively output an "accumulator" containing a reversed list of
+ printing entities (string, char, flus, ...) in a buffer. *)
+(* Differ from Printf.bufput_acc by the interpretation of formatting. *)
+(* Used as a continuation of CamlinternalFormat.make_printf. *)
+let rec strput_acc ppf acc = match acc with
+ | Acc_string (Acc_formatting_lit (p, Magic_size (_, size)), s) ->
+ strput_acc ppf p;
+ pp_print_as_size ppf (size_of_int size) s;
+ | Acc_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);
+ | Acc_delay (Acc_formatting_lit (p, Magic_size (_, size)), f) ->
+ strput_acc ppf p;
+ 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')
+ | Acc_formatting_gen (p, Acc_open_box acc') ->
+ let () = strput_acc ppf p in
+ let (indent, bty) = open_box_of_string (compute_tag strput_acc acc') in
+ pp_open_box_gen ppf indent bty
+ | Acc_string (p, s) -> strput_acc ppf p; pp_print_string ppf s;
+ | Acc_char (p, c) -> strput_acc ppf p; pp_print_char ppf c;
+ | Acc_delay (p, f) -> strput_acc ppf p; pp_print_string ppf (f ());
+ | Acc_flush p -> strput_acc ppf p; pp_print_flush ppf ();
+ | Acc_invalid_arg (p, msg) -> strput_acc ppf p; invalid_arg msg;
+ | End_of_acc -> ()
(**************************************************************
@@ -1381,30 +1157,37 @@ let mkprintf to_s get_out k fmt =
**************************************************************)
-let kfprintf k ppf = mkprintf false (fun _ -> ppf) k;;
-let ikfprintf k ppf = Tformat.kapr (fun _ _ -> Obj.magic (k ppf));;
-
-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 ksprintf k =
+let kfprintf k o (Format (fmt, _)) =
+ make_printf (fun o acc -> output_acc o acc; k o) o End_of_acc fmt
+let ikfprintf k x (Format (fmt, _)) =
+ make_printf (fun _ _ -> k x) x End_of_acc fmt
+
+let fprintf ppf fmt = kfprintf ignore ppf fmt
+let ifprintf ppf fmt = ikfprintf ignore ppf fmt
+let printf fmt = fprintf std_formatter fmt
+let eprintf fmt = fprintf err_formatter fmt
+
+let ksprintf k (Format (fmt, _)) =
+ let k' () acc =
+ let b = Buffer.create 512 in
+ let ppf = formatter_of_buffer b in
+ strput_acc ppf acc;
+ pp_flush_queue ppf false;
+ k (Buffer.contents b) in
+ make_printf k' () End_of_acc fmt
+
+let sprintf fmt =
+ ksprintf (fun s -> s) fmt
+
+let asprintf (Format (fmt, _)) =
let b = Buffer.create 512 in
- let k ppf = k (string_out b ppf) in
- let ppf = formatter_of_buffer b in
- let get_out _ = ppf in
- mkprintf true get_out k
-;;
-
-let sprintf fmt = ksprintf (fun s -> s) fmt;;
-
-let asprintf fmt =
- let b = Buffer.create 512 in
- let k ppf = string_out b ppf in
- let ppf = formatter_of_buffer b in
- let get_out _ = ppf in
- mkprintf false get_out k fmt;;
+ let ppf = formatter_of_buffer b in
+ let k' : (formatter -> (formatter, unit) acc -> string)
+ = fun ppf acc ->
+ output_acc ppf acc;
+ pp_flush_queue ppf false;
+ Buffer.contents b in
+ make_printf k' ppf End_of_acc fmt
(**************************************************************
@@ -1412,15 +1195,10 @@ let asprintf fmt =
**************************************************************)
-let kbprintf k b =
- mkprintf false (fun _ -> formatter_of_buffer b) k
-;;
-
(* Deprecated error prone function bprintf. *)
-let bprintf b =
- let k ppf = pp_flush_queue ppf false in
- kbprintf k b
-;;
+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
(* Deprecated alias for ksprintf. *)
let kprintf = ksprintf;;
diff --git a/stdlib/gc.mli b/stdlib/gc.mli
index d2f2d97611..c4ed399300 100644
--- a/stdlib/gc.mli
+++ b/stdlib/gc.mli
@@ -249,7 +249,7 @@ val finalise : ('a -> unit) -> 'a -> unit
another copy is still in use by the program.
- The results of calling {!String.make}, {!String.create},
+ The results of calling {!String.make}, {!Bytes.make}, {!Bytes.create},
{!Array.make}, and {!Pervasives.ref} are guaranteed to be
heap-allocated and non-constant except when the length argument is [0].
*)
diff --git a/stdlib/genlex.ml b/stdlib/genlex.ml
index dc80727df2..4f52b18654 100644
--- a/stdlib/genlex.ml
+++ b/stdlib/genlex.ml
@@ -21,7 +21,7 @@ type token =
(* The string buffering machinery *)
-let initial_buffer = String.create 32
+let initial_buffer = Bytes.create 32
let buffer = ref initial_buffer
let bufpos = ref 0
@@ -29,16 +29,16 @@ let bufpos = ref 0
let reset_buffer () = buffer := initial_buffer; bufpos := 0
let store c =
- if !bufpos >= String.length !buffer then
- begin
- let newbuffer = String.create (2 * !bufpos) in
- String.blit !buffer 0 newbuffer 0 !bufpos; buffer := newbuffer
- end;
- String.set !buffer !bufpos c;
+ if !bufpos >= Bytes.length !buffer then begin
+ let newbuffer = Bytes.create (2 * !bufpos) in
+ Bytes.blit !buffer 0 newbuffer 0 !bufpos;
+ buffer := newbuffer
+ end;
+ Bytes.set !buffer !bufpos c;
incr bufpos
let get_string () =
- let s = String.sub !buffer 0 !bufpos in buffer := initial_buffer; s
+ let s = Bytes.sub_string !buffer 0 !bufpos in buffer := initial_buffer; s
(* The lexer *)
diff --git a/stdlib/lexing.ml b/stdlib/lexing.ml
index 53748ad867..d2231fbe9b 100644
--- a/stdlib/lexing.ml
+++ b/stdlib/lexing.ml
@@ -29,7 +29,7 @@ let dummy_pos = {
type lexbuf =
{ refill_buff : lexbuf -> unit;
- mutable lex_buffer : string;
+ mutable lex_buffer : bytes;
mutable lex_buffer_len : int;
mutable lex_abs_pos : int;
mutable lex_start_pos : int;
@@ -81,7 +81,7 @@ let new_engine tbl state buf =
let lex_refill read_fun aux_buffer lexbuf =
let read =
- read_fun aux_buffer (String.length aux_buffer) in
+ read_fun aux_buffer (Bytes.length aux_buffer) in
let n =
if read > 0
then read
@@ -90,16 +90,16 @@ let lex_refill read_fun aux_buffer lexbuf =
<-------|---------------------|----------->
| junk | valid data | junk |
^ ^ ^ ^
- 0 start_pos buffer_end String.length buffer
+ 0 start_pos buffer_end Bytes.length buffer
*)
- if lexbuf.lex_buffer_len + n > String.length lexbuf.lex_buffer then begin
+ if lexbuf.lex_buffer_len + n > Bytes.length lexbuf.lex_buffer then begin
(* There is not enough space at the end of the buffer *)
if lexbuf.lex_buffer_len - lexbuf.lex_start_pos + n
- <= String.length lexbuf.lex_buffer
+ <= Bytes.length lexbuf.lex_buffer
then begin
(* But there is enough space if we reclaim the junk at the beginning
of the buffer *)
- String.blit lexbuf.lex_buffer lexbuf.lex_start_pos
+ Bytes.blit lexbuf.lex_buffer lexbuf.lex_start_pos
lexbuf.lex_buffer 0
(lexbuf.lex_buffer_len - lexbuf.lex_start_pos)
end else begin
@@ -107,12 +107,12 @@ let lex_refill read_fun aux_buffer lexbuf =
space since n <= String.length aux_buffer <= String.length buffer.
Watch out for string length overflow, though. *)
let newlen =
- min (2 * String.length lexbuf.lex_buffer) Sys.max_string_length in
+ min (2 * Bytes.length lexbuf.lex_buffer) Sys.max_string_length in
if lexbuf.lex_buffer_len - lexbuf.lex_start_pos + n > newlen
then failwith "Lexing.lex_refill: cannot grow buffer";
- let newbuf = String.create newlen in
+ let newbuf = Bytes.create newlen in
(* Copy the valid data to the beginning of the new buffer *)
- String.blit lexbuf.lex_buffer lexbuf.lex_start_pos
+ Bytes.blit lexbuf.lex_buffer lexbuf.lex_start_pos
newbuf 0
(lexbuf.lex_buffer_len - lexbuf.lex_start_pos);
lexbuf.lex_buffer <- newbuf
@@ -133,9 +133,7 @@ let lex_refill read_fun aux_buffer lexbuf =
done
end;
(* There is now enough space at the end of the buffer *)
- String.blit aux_buffer 0
- lexbuf.lex_buffer lexbuf.lex_buffer_len
- n;
+ Bytes.blit aux_buffer 0 lexbuf.lex_buffer lexbuf.lex_buffer_len n;
lexbuf.lex_buffer_len <- lexbuf.lex_buffer_len + n
let zero_pos = {
@@ -146,8 +144,8 @@ let zero_pos = {
};;
let from_function f =
- { refill_buff = lex_refill f (String.create 512);
- lex_buffer = String.create 1024;
+ { refill_buff = lex_refill f (Bytes.create 512);
+ lex_buffer = Bytes.create 1024;
lex_buffer_len = 0;
lex_abs_pos = 0;
lex_start_pos = 0;
@@ -165,7 +163,8 @@ let from_channel ic =
let from_string s =
{ refill_buff = (fun lexbuf -> lexbuf.lex_eof_reached <- true);
- lex_buffer = s ^ "";
+ lex_buffer = Bytes.of_string s; (* have to make a copy for compatibility
+ with unsafe-string mode *)
lex_buffer_len = String.length s;
lex_abs_pos = 0;
lex_start_pos = 0;
@@ -180,37 +179,31 @@ let from_string s =
let lexeme lexbuf =
let len = lexbuf.lex_curr_pos - lexbuf.lex_start_pos in
- let s = String.create len in
- String.unsafe_blit lexbuf.lex_buffer lexbuf.lex_start_pos s 0 len;
- s
+ Bytes.sub_string lexbuf.lex_buffer lexbuf.lex_start_pos len
let sub_lexeme lexbuf i1 i2 =
let len = i2-i1 in
- let s = String.create len in
- String.unsafe_blit lexbuf.lex_buffer i1 s 0 len;
- s
+ Bytes.sub_string lexbuf.lex_buffer i1 len
let sub_lexeme_opt lexbuf i1 i2 =
if i1 >= 0 then begin
let len = i2-i1 in
- let s = String.create len in
- String.unsafe_blit lexbuf.lex_buffer i1 s 0 len;
- Some s
+ Some (Bytes.sub_string lexbuf.lex_buffer i1 len)
end else begin
None
end
-let sub_lexeme_char lexbuf i = lexbuf.lex_buffer.[i]
+let sub_lexeme_char lexbuf i = Bytes.get lexbuf.lex_buffer i
let sub_lexeme_char_opt lexbuf i =
if i >= 0 then
- Some lexbuf.lex_buffer.[i]
+ Some (Bytes.get lexbuf.lex_buffer i)
else
None
let lexeme_char lexbuf i =
- String.get lexbuf.lex_buffer (lexbuf.lex_start_pos + i)
+ Bytes.get lexbuf.lex_buffer (lexbuf.lex_start_pos + i)
let lexeme_start lexbuf = lexbuf.lex_start_p.pos_cnum;;
let lexeme_end lexbuf = lexbuf.lex_curr_p.pos_cnum;;
diff --git a/stdlib/lexing.mli b/stdlib/lexing.mli
index 6d5406d693..30898670b7 100644
--- a/stdlib/lexing.mli
+++ b/stdlib/lexing.mli
@@ -46,7 +46,7 @@ val dummy_pos : position;;
type lexbuf =
{ refill_buff : lexbuf -> unit;
- mutable lex_buffer : string;
+ mutable lex_buffer : bytes;
mutable lex_buffer_len : int;
mutable lex_abs_pos : int;
mutable lex_start_pos : int;
@@ -84,12 +84,12 @@ val from_string : string -> lexbuf
the string. An end-of-input condition is generated when the
end of the string is reached. *)
-val from_function : (string -> int -> int) -> lexbuf
+val from_function : (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 character string [s] and a character
- count [n]. The function should put [n] characters or less in [s],
- starting at character number 0, and return the number of characters
+ function, giving it a byte sequence [s] and a byte
+ count [n]. The function should put [n] bytes or fewer in [s],
+ starting at index 0, and return the number of bytes
provided. A return value of 0 means end of input. *)
diff --git a/stdlib/map.mli b/stdlib/map.mli
index 6dd371b52c..abf4531618 100644
--- a/stdlib/map.mli
+++ b/stdlib/map.mli
@@ -19,6 +19,26 @@
All operations over maps are purely applicative (no side-effects).
The implementation uses balanced binary trees, and therefore searching
and insertion take time logarithmic in the size of the map.
+
+ For instance:
+ {[
+ module IntPairs =
+ struct
+ type t = int * int
+ let compare (x0,y0) (x1,y1) =
+ match Pervasives.compare x0 x1 with
+ 0 -> Pervasives.compare y0 y1
+ | c -> c
+ end
+
+ module PairsMap = Map.Make(IntPairs)
+
+ let m = PairsMap.(empty |> add (0,1) "hello" |> add (1,0) "world")
+ ]}
+
+ This creates a new module [PairsMap], with a new type ['a PairsMap.t]
+ of maps from [int * int] to ['a]. In this example, [m] contains [string]
+ values so its type is [string PairsMap.t].
*)
module type OrderedType =
diff --git a/stdlib/marshal.ml b/stdlib/marshal.ml
index 7a65a16a37..4f59a3ef21 100644
--- a/stdlib/marshal.ml
+++ b/stdlib/marshal.ml
@@ -19,35 +19,39 @@ type extern_flags =
external to_channel: out_channel -> 'a -> extern_flags list -> unit
= "caml_output_value"
+external to_bytes: 'a -> extern_flags list -> bytes
+ = "caml_output_value_to_string"
external to_string: 'a -> extern_flags list -> string
= "caml_output_value_to_string"
external to_buffer_unsafe:
- string -> int -> int -> 'a -> extern_flags list -> int
+ bytes -> int -> int -> 'a -> extern_flags list -> int
= "caml_output_value_to_buffer"
let to_buffer buff ofs len v flags =
- if ofs < 0 || len < 0 || ofs > String.length buff - len
+ if ofs < 0 || len < 0 || ofs > Bytes.length buff - len
then invalid_arg "Marshal.to_buffer: substring out of bounds"
else to_buffer_unsafe buff ofs len v flags
external from_channel: in_channel -> 'a = "caml_input_value"
-external from_string_unsafe: string -> int -> 'a
+external from_bytes_unsafe: bytes -> int -> 'a
= "caml_input_value_from_string"
-external data_size_unsafe: string -> int -> int = "caml_marshal_data_size"
+external data_size_unsafe: bytes -> int -> int = "caml_marshal_data_size"
let header_size = 20
let data_size buff ofs =
- if ofs < 0 || ofs > String.length buff - header_size
+ if ofs < 0 || ofs > Bytes.length buff - header_size
then invalid_arg "Marshal.data_size"
else data_size_unsafe buff ofs
let total_size buff ofs = header_size + data_size buff ofs
-let from_string buff ofs =
- if ofs < 0 || ofs > String.length buff - header_size
- then invalid_arg "Marshal.from_size"
+let from_bytes buff ofs =
+ if ofs < 0 || ofs > Bytes.length buff - header_size
+ then invalid_arg "Marshal.from_bytes"
else begin
let len = data_size_unsafe buff ofs in
- if ofs > String.length buff - (header_size + len)
- then invalid_arg "Marshal.from_string"
- else from_string_unsafe buff ofs
+ if ofs > Bytes.length buff - (header_size + len)
+ then invalid_arg "Marshal.from_bytes"
+ else from_bytes_unsafe buff ofs
end
+
+let from_string buff ofs = from_bytes (Bytes.unsafe_of_string buff) ofs
diff --git a/stdlib/marshal.mli b/stdlib/marshal.mli
index f12af9fd9d..37f0345b38 100644
--- a/stdlib/marshal.mli
+++ b/stdlib/marshal.mli
@@ -33,12 +33,13 @@
Anything can happen at run-time if the object in the file does not
belong to the given type.
- OCaml exception values (of type [exn]) returned by the unmarhsaller
- should not be pattern-matched over through [match ... with] or [try
- ... with], because unmarshalling does not preserve the information
- required for matching their exception constructor. Structural
- equalities with other exception values, or most other uses such as
- Printexc.to_string, will still work as expected.
+ Values of extensible variant types, for example exceptions (of
+ extensible type [exn]), returned by the unmarhsaller should not be
+ pattern-matched over through [match ... with] or [try ... with],
+ because unmarshalling does not preserve the information required for
+ matching their constructors. Structural equalities with other
+ extensible variant values does not work either. Most other uses such
+ as Printexc.to_string, will still work as expected.
The representation of marshaled values is not human-readable,
and uses bytes that are not printable characters. Therefore,
@@ -47,7 +48,7 @@
[open_out_bin] or [open_in_bin]; channels opened in text mode will
cause unmarshaling errors on platforms where text channels behave
differently than binary channels, e.g. Windows.
-*)
+ *)
type extern_flags =
No_sharing (** Don't preserve sharing *)
@@ -74,17 +75,26 @@ val to_channel : out_channel -> 'a -> extern_flags list -> unit
byte representations if [v] actually contains sharing,
or even non-termination if [v] contains cycles.
- If [flags] does not contain [Marshal.Closures],
- marshaling fails when it encounters a functional value
- inside [v]: only 'pure' data structures, containing neither
- functions nor objects, can safely be transmitted between
- different programs. If [flags] contains [Marshal.Closures],
- functional values will be marshaled as a position in the code
- of the program. In this case, the output of marshaling can
- only be read back in processes that run exactly the same program,
- with exactly the same compiled code. (This is checked
- at un-marshaling time, using an MD5 digest of the code
- transmitted along with the code position.)
+ If [flags] does not contain [Marshal.Closures], marshaling fails
+ when it encounters a functional value inside [v]: only 'pure' data
+ structures, containing neither functions nor objects, can safely be
+ transmitted between different programs. If [flags] contains
+ [Marshal.Closures], functional values will be marshaled as a the
+ position in the code of the program together with the values
+ corresponding to the free variables captured in the closure. In
+ this case, the output of marshaling can only be read back in
+ processes that run exactly the same program, with exactly the same
+ compiled code. (This is checked at un-marshaling time, using an MD5
+ digest of the code transmitted along with the code position.)
+
+ The exact definition of which free variables are captured in a
+ closure is not specified and can very between bytecode and native
+ code (and according to optimization flags). In particular, a
+ function value accessing a global reference may or may not include
+ the reference in its closure. If it does, unmarshaling the
+ corresponding closure will create a new reference, different from
+ the global one.
+
If [flags] contains [Marshal.Compat_32], marshaling fails when
it encounters an integer value outside the range [[-2{^30}, 2{^30}-1]]
@@ -99,19 +109,24 @@ val to_channel : out_channel -> 'a -> extern_flags list -> unit
it has no effect if marshaling is performed on a 32-bit platform.
*)
-external to_string :
- 'a -> extern_flags list -> string = "caml_output_value_to_string"
-(** [Marshal.to_string v flags] returns a string containing
- the representation of [v] as a sequence of bytes.
+external to_bytes :
+ 'a -> extern_flags list -> bytes = "caml_output_value_to_string"
+(** [Marshal.to_bytes v flags] returns a byte sequence containing
+ the representation of [v].
The [flags] argument has the same meaning as for
{!Marshal.to_channel}. *)
-val to_buffer : string -> int -> int -> 'a -> extern_flags list -> int
+external to_string :
+ 'a -> extern_flags list -> string = "caml_output_value_to_string"
+(** Same as [to_bytes] but return the result as a string instead of
+ a byte sequence. *)
+
+val to_buffer : bytes -> int -> int -> 'a -> extern_flags list -> int
(** [Marshal.to_buffer buff ofs len v flags] marshals the value [v],
- storing its byte representation in the string [buff],
- starting at character number [ofs], and writing at most
- [len] characters. It returns the number of characters
- actually written to the string. If the byte representation
+ storing its byte representation in the sequence [buff],
+ starting at index [ofs], and writing at most
+ [len] bytes. It returns the number of bytes
+ actually written to the sequence. If the byte representation
of [v] does not fit in [len] characters, the exception [Failure]
is raised. *)
@@ -121,36 +136,40 @@ val from_channel : in_channel -> 'a
one of the [Marshal.to_*] functions, and reconstructs and
returns the corresponding value.*)
-val from_string : string -> int -> 'a
-(** [Marshal.from_string buff ofs] unmarshals a structured value
+val from_bytes : bytes -> int -> 'a
+(** [Marshal.from_bytes buff ofs] unmarshals a structured value
like {!Marshal.from_channel} does, except that the byte
representation is not read from a channel, but taken from
- the string [buff], starting at position [ofs]. *)
+ the byte sequence [buff], starting at position [ofs]. *)
+
+val from_string : string -> int -> 'a
+(** Same as [from_bytes] but take a string as argument instead of a
+ byte sequence. *)
val header_size : int
(** The bytes representing a marshaled value are composed of
a fixed-size header and a variable-sized data part,
whose size can be determined from the header.
- {!Marshal.header_size} is the size, in characters, of the header.
- {!Marshal.data_size}[ buff ofs] is the size, in characters,
+ {!Marshal.header_size} is the size, in bytes, of the header.
+ {!Marshal.data_size}[ buff ofs] is the size, in bytes,
of the data part, assuming a valid header is stored in
[buff] starting at position [ofs].
Finally, {!Marshal.total_size} [buff ofs] is the total size,
- in characters, of the marshaled value.
+ in bytes, of the marshaled value.
Both {!Marshal.data_size} and {!Marshal.total_size} raise [Failure]
if [buff], [ofs] does not contain a valid header.
To read the byte representation of a marshaled value into
- a string buffer, the program needs to read first
- {!Marshal.header_size} characters into the buffer,
+ a byte sequence, the program needs to read first
+ {!Marshal.header_size} bytes into the sequence,
then determine the length of the remainder of the
representation using {!Marshal.data_size},
- make sure the buffer is large enough to hold the remaining
- data, then read it, and finally call {!Marshal.from_string}
+ make sure the sequence is large enough to hold the remaining
+ data, then read it, and finally call {!Marshal.from_bytes}
to unmarshal the value. *)
-val data_size : string -> int -> int
+val data_size : bytes -> int -> int
(** See {!Marshal.header_size}.*)
-val total_size : string -> int -> int
+val total_size : bytes -> int -> int
(** See {!Marshal.header_size}.*)
diff --git a/stdlib/obj.ml b/stdlib/obj.ml
index a6f11586e8..d054d35c42 100644
--- a/stdlib/obj.ml
+++ b/stdlib/obj.ml
@@ -33,9 +33,9 @@ external truncate : t -> int -> unit = "caml_obj_truncate"
external add_offset : t -> Int32.t -> t = "caml_obj_add_offset"
let marshal (obj : t) =
- Marshal.to_string obj []
+ Marshal.to_bytes obj []
let unmarshal str pos =
- (Marshal.from_string str pos, pos + Marshal.total_size str pos)
+ (Marshal.from_bytes str pos, pos + Marshal.total_size str pos)
let lazy_tag = 246
let closure_tag = 247
@@ -56,3 +56,28 @@ let final_tag = custom_tag
let int_tag = 1000
let out_of_heap_tag = 1001
let unaligned_tag = 1002
+
+let extension_slot 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 raise Not_found
+ in
+ if (tag name) = string_tag then slot
+ else raise Not_found
+
+let extension_name x =
+ try
+ let slot = extension_slot x in
+ (obj (field slot 0) : string)
+ with Not_found -> invalid_arg "Obj.extension_name"
+
+let extension_id x =
+ try
+ let slot = extension_slot x in
+ (obj (field slot 1) : int)
+ with Not_found -> invalid_arg "Obj.extension_id"
diff --git a/stdlib/obj.mli b/stdlib/obj.mli
index 9a5bd721d5..5181e2a22b 100644
--- a/stdlib/obj.mli
+++ b/stdlib/obj.mli
@@ -43,18 +43,21 @@ val infix_tag : int
val forward_tag : int
val no_scan_tag : int
val abstract_tag : int
-val string_tag : int
+val string_tag : int (* both [string] and [bytes] *)
val double_tag : int
val double_array_tag : int
val custom_tag : int
-val final_tag : int (* DEPRECATED *)
+val final_tag : int [@@ocaml.deprecated]
val int_tag : int
val out_of_heap_tag : int
val unaligned_tag : int (* should never happen @since 3.11.0 *)
+val extension_name : 'a -> string
+val extension_id : 'a -> int
+
(** The following two functions are deprecated. Use module {!Marshal}
instead. *)
-val marshal : t -> string
-val unmarshal : string -> int -> t * int
+val marshal : t -> bytes [@@ocaml.deprecated]
+val unmarshal : bytes -> int -> t * int [@@ocaml.deprecated]
diff --git a/stdlib/pervasives.ml b/stdlib/pervasives.ml
index 9f88480bfa..8f9e423f95 100644
--- a/stdlib/pervasives.ml
+++ b/stdlib/pervasives.ml
@@ -46,9 +46,7 @@ external __MODULE__ : string = "%loc_MODULE"
external __POS__ : string * int * int * int = "%loc_POS"
external __LOC_OF__ : 'a -> string * 'a = "%loc_LOC"
-external __FILE_OF__ : 'a -> string * 'a = "%loc_FILE"
external __LINE_OF__ : 'a -> int * 'a = "%loc_LINE"
-external __MODULE_OF__ : 'a -> string * 'a = "%loc_MODULE"
external __POS_OF__ : 'a -> (string * int * int * int) * 'a = "%loc_POS"
(* Comparisons *)
@@ -83,7 +81,7 @@ 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 = "%mulint"
external ( / ) : int -> int -> int = "%divint"
external ( mod ) : int -> int -> int = "%modint"
@@ -164,19 +162,24 @@ type fpclass =
| FP_nan
external classify_float : float -> fpclass = "caml_classify_float"
-(* String operations -- more in module String *)
+(* String and byte sequence operations -- more in modules String and Bytes *)
external string_length : string -> int = "%string_length"
-external string_create : int -> string = "caml_create_string"
-external string_blit : string -> int -> string -> int -> int -> unit
+external bytes_length : bytes -> int = "%string_length"
+external bytes_create : int -> bytes = "caml_create_string"
+external string_blit : string -> int -> bytes -> int -> int -> unit
= "caml_blit_string" "noalloc"
+external bytes_blit : bytes -> int -> bytes -> int -> int -> unit
+ = "caml_blit_string" "noalloc"
+external bytes_unsafe_to_string : bytes -> string = "%identity"
+external bytes_unsafe_of_string : string -> bytes = "%identity"
let ( ^ ) s1 s2 =
let l1 = string_length s1 and l2 = string_length s2 in
- let s = string_create (l1 + l2) in
+ let s = bytes_create (l1 + l2) in
string_blit s1 0 s 0 l1;
string_blit s2 0 s l1 l2;
- s
+ bytes_unsafe_to_string s
(* Character operations -- more in module Char *)
@@ -219,16 +222,13 @@ let string_of_int n =
format_int "%d" n
external int_of_string : string -> int = "caml_int_of_string"
-
-module String = struct
- external get : string -> int -> char = "%string_safe_get"
-end
+external string_get : string -> int -> char = "%string_safe_get"
let valid_float_lexem s =
let l = string_length s in
let rec loop i =
if i >= l then s ^ "." else
- match s.[i] with
+ match string_get s i with
| '0' .. '9' | '-' -> loop (i + 1)
| _ -> s
in
@@ -288,19 +288,25 @@ let flush_all () =
| a :: l -> (try flush a with _ -> ()); iter l
in iter (out_channels_list ())
-external unsafe_output : out_channel -> string -> int -> int -> unit
+external unsafe_output : out_channel -> bytes -> int -> int -> unit
= "caml_ml_output"
external output_char : out_channel -> char -> unit = "caml_ml_output_char"
+let output_bytes oc s =
+ unsafe_output oc s 0 (bytes_length s)
+
let output_string oc s =
- unsafe_output oc s 0 (string_length s)
+ unsafe_output oc (bytes_unsafe_of_string s) 0 (string_length s)
let output oc s ofs len =
- if ofs < 0 || len < 0 || ofs > string_length s - len
+ if ofs < 0 || len < 0 || ofs > bytes_length s - len
then invalid_arg "output"
else unsafe_output oc s ofs len
+let output_substring oc s ofs len =
+ output oc (bytes_unsafe_of_string s) ofs len
+
external output_byte : out_channel -> int -> unit = "caml_ml_output_char"
external output_binary_int : out_channel -> int -> unit = "caml_ml_output_int"
@@ -332,11 +338,11 @@ let open_in_bin name =
external input_char : in_channel -> char = "caml_ml_input_char"
-external unsafe_input : in_channel -> string -> int -> int -> int
+external unsafe_input : in_channel -> bytes -> int -> int -> int
= "caml_ml_input"
let input ic s ofs len =
- if ofs < 0 || len < 0 || ofs > string_length s - len
+ if ofs < 0 || len < 0 || ofs > bytes_length s - len
then invalid_arg "input"
else unsafe_input ic s ofs len
@@ -349,39 +355,44 @@ let rec unsafe_really_input ic s ofs len =
end
let really_input ic s ofs len =
- if ofs < 0 || len < 0 || ofs > string_length s - len
+ if ofs < 0 || len < 0 || ofs > bytes_length s - len
then invalid_arg "really_input"
else unsafe_really_input ic s ofs len
+let really_input_string ic len =
+ let s = bytes_create len in
+ really_input ic s 0 len;
+ bytes_unsafe_to_string s
+
external input_scan_line : in_channel -> int = "caml_ml_input_scan_line"
let input_line chan =
let rec build_result buf pos = function
[] -> buf
| hd :: tl ->
- let len = string_length hd in
- string_blit hd 0 buf (pos - len) len;
+ let len = bytes_length hd in
+ bytes_blit hd 0 buf (pos - len) len;
build_result buf (pos - len) tl in
let rec scan accu len =
let n = input_scan_line chan in
if n = 0 then begin (* n = 0: we are at EOF *)
match accu with
[] -> raise End_of_file
- | _ -> build_result (string_create len) len accu
+ | _ -> build_result (bytes_create len) len accu
end else if n > 0 then begin (* n > 0: newline found in buffer *)
- let res = string_create (n - 1) in
+ let res = bytes_create (n - 1) in
ignore (unsafe_input chan res 0 (n - 1));
ignore (input_char chan); (* skip the newline *)
match accu with
[] -> res
| _ -> let len = len + n - 1 in
- build_result (string_create len) len (res :: accu)
+ build_result (bytes_create len) len (res :: accu)
end else begin (* n < 0: newline not found *)
- let beg = string_create (-n) in
+ let beg = bytes_create (-n) in
ignore(unsafe_input chan beg 0 (-n));
scan (beg :: accu) (len - n)
end
- in scan [] 0
+ in bytes_unsafe_to_string (scan [] 0)
external input_byte : in_channel -> int = "caml_ml_input_char"
external input_binary_int : in_channel -> int = "caml_ml_input_int"
@@ -398,6 +409,7 @@ external set_binary_mode_in : in_channel -> bool -> unit
let print_char c = output_char stdout c
let print_string s = output_string stdout s
+let print_bytes s = output_bytes stdout s
let print_int i = output_string stdout (string_of_int i)
let print_float f = output_string stdout (string_of_float f)
let print_endline s =
@@ -408,6 +420,7 @@ let print_newline () = output_char stdout '\n'; flush stdout
let prerr_char c = output_char stderr c
let prerr_string s = output_string stderr s
+let prerr_bytes s = output_bytes stderr s
let prerr_int i = output_string stderr (string_of_int i)
let prerr_float f = output_string stderr (string_of_float f)
let prerr_endline s =
@@ -434,33 +447,25 @@ module LargeFile =
end
(* Formats *)
+
+type ('a, 'b, 'c, 'd, 'e, 'f) format6
+ = ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.format6
+ = Format of ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.fmt
+ * string
+
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 (Format (fmt, str)) = str
+
external format_of_string :
('a, 'b, 'c, 'd, 'e, 'f) format6 ->
('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity"
-external format_to_string :
- ('a, 'b, 'c, 'd, 'e, 'f) format6 -> string = "%identity"
-external string_to_format :
- string -> ('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity"
-
-let (( ^^ ) :
- ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
- ('f, 'b, 'c, 'e, 'g, 'h) format6 ->
- ('a, 'b, 'c, 'd, 'g, 'h) format6) =
- fun fmt1 fmt2 ->
- string_to_format (format_to_string fmt1 ^ "%," ^ format_to_string fmt2)
-;;
-
-let string_of_format fmt =
- let s = format_to_string fmt in
- let l = string_length s in
- let r = string_create l in
- string_blit s 0 r 0 l;
- r
+let (^^) (Format (fmt1, str1)) (Format (fmt2, str2)) =
+ Format (CamlinternalFormatBasics.concat_fmt fmt1 fmt2,
+ str1 ^ "%," ^ str2)
(* Miscellaneous *)
diff --git a/stdlib/pervasives.mli b/stdlib/pervasives.mli
index 1ee09984c7..77cb1e92ce 100644
--- a/stdlib/pervasives.mli
+++ b/stdlib/pervasives.mli
@@ -14,8 +14,8 @@
(** The initially opened module.
This module provides the basic operations over the built-in types
- (numbers, booleans, strings, exceptions, references, lists, arrays,
- input-output channels, ...).
+ (numbers, booleans, byte sequences, strings, exceptions, references,
+ lists, arrays, input-output channels, ...).
This module is automatically opened at the beginning of each compilation.
All components of this module can therefore be referred by their short
@@ -68,7 +68,7 @@ external ( <= ) : 'a -> 'a -> bool = "%lessequal"
external ( >= ) : 'a -> 'a -> bool = "%greaterequal"
(** Structural ordering functions. These functions coincide with
- the usual orderings over integers, characters, strings
+ the usual orderings over integers, characters, strings, byte sequences
and floating-point numbers, and extend them to a
total ordering over all types.
The ordering is compatible with [( = )]. As in the case
@@ -107,7 +107,7 @@ val max : 'a -> 'a -> 'a
external ( == ) : 'a -> 'a -> bool = "%eq"
(** [e1 == e2] tests for physical equality of [e1] and [e2].
- On mutable types such as references, arrays, strings, records with
+ On mutable types such as references, arrays, byte sequences, records with
mutable fields and objects with mutable instance variables,
[e1 == e2] is true if and only if physical modification of [e1]
also affects [e2].
@@ -143,16 +143,41 @@ external ( or ) : bool -> bool -> bool = "%sequor"
(** {6 Debugging} *)
external __LOC__ : string = "%loc_LOC"
+(** [__LOC__] returns the location at which this expression appears in
+ the file currently being parsed by the compiler, with the standard
+ error format of OCaml: "File %S, line %d, characters %d-%d" *)
external __FILE__ : string = "%loc_FILE"
+(** [__FILE__] returns the name of the file currently being
+ parsed by the compiler. *)
external __LINE__ : int = "%loc_LINE"
+(** [__LINE__] returns the line number at which this expression
+ appears in the file currently being parsed by the compiler. *)
external __MODULE__ : string = "%loc_MODULE"
+(** [__MODULE__] returns the module name of the file being
+ parsed by the compiler. *)
external __POS__ : string * int * int * int = "%loc_POS"
+(** [__POS__] returns a tuple [(file,lnum,cnum,enum)], corresponding
+ to the location at which this expression appears in the file
+ currently being parsed by the compiler. [file] is the current
+ filename, [lnum] the line number, [cnum] the character position in
+ the line and [enum] the last character position in the line. *)
external __LOC_OF__ : 'a -> string * 'a = "%loc_LOC"
-external __FILE_OF__ : 'a -> string * 'a = "%loc_FILE"
+(** [__LOC_OF__ expr] returns a pair [(loc, expr)] where [loc] is the
+ location of [expr] in the file currently being parsed by the
+ compiler, with the standard error format of OCaml: "File %S, line
+ %d, characters %d-%d" *)
external __LINE_OF__ : 'a -> int * 'a = "%loc_LINE"
-external __MODULE_OF__ : 'a -> string * 'a = "%loc_MODULE"
+(** [__LINE__ expr] returns a pair [(line, expr)], where [line] is the
+ line number at which the expression [expr] appears in the file
+ currently being parsed by the compiler. *)
external __POS_OF__ : 'a -> (string * int * int * int) * 'a = "%loc_POS"
+(** [__POS_OF__ expr] returns a pair [(expr,loc)], where [loc] is a
+ tuple [(file,lnum,cnum,enum)] corresponding to the location at
+ which the expression [expr] appears in the file currently being
+ parsed by the compiler. [file] is the current filename, [lnum] the
+ line number, [cnum] the character position in the line and [enum]
+ the last character position in the line. *)
(** {6 Composition operators} *)
@@ -566,6 +591,9 @@ val print_char : char -> unit
val print_string : string -> unit
(** Print a string on standard output. *)
+val print_bytes : bytes -> unit
+(** Print a byte sequence on standard output. *)
+
val print_int : int -> unit
(** Print an integer, in decimal, on standard output. *)
@@ -590,6 +618,9 @@ val prerr_char : char -> unit
val prerr_string : string -> unit
(** Print a string on standard error. *)
+val prerr_bytes : bytes -> unit
+(** Print a byte sequence on standard error. *)
+
val prerr_int : int -> unit
(** Print an integer, in decimal, on standard error. *)
@@ -597,8 +628,8 @@ val prerr_float : float -> unit
(** Print a floating-point number, in decimal, on standard error. *)
val prerr_endline : string -> unit
-(** Print a string, followed by a newline character on standard error
- and flush standard error. *)
+(** Print a string, followed by a newline character on standard
+ error and flush standard error. *)
val prerr_newline : unit -> unit
(** Print a newline character on standard error, and flush
@@ -674,11 +705,18 @@ val output_char : out_channel -> char -> unit
val output_string : out_channel -> string -> unit
(** Write the string on the given output channel. *)
-val output : out_channel -> string -> int -> int -> unit
-(** [output oc buf pos len] writes [len] characters from string [buf],
+val output_bytes : out_channel -> bytes -> unit
+(** Write the byte sequence on the given output channel. *)
+
+val output : out_channel -> bytes -> int -> int -> unit
+(** [output oc buf pos len] writes [len] characters from byte sequence [buf],
starting at offset [pos], to the given output channel [oc].
Raise [Invalid_argument "output"] if [pos] and [len] do not
- designate a valid substring of [buf]. *)
+ designate a valid range of [buf]. *)
+
+val output_substring : out_channel -> string -> int -> int -> unit
+(** Same as [output] but take a string as argument instead of
+ a byte sequence. *)
val output_byte : out_channel -> int -> unit
(** Write one 8-bit integer (as the single character with that code)
@@ -769,9 +807,9 @@ val input_line : in_channel -> string
Raise [End_of_file] if the end of the file is reached
at the beginning of line. *)
-val input : in_channel -> string -> int -> int -> int
+val input : in_channel -> bytes -> int -> int -> int
(** [input ic buf pos len] reads up to [len] characters from
- the given channel [ic], storing them in string [buf], starting at
+ the given channel [ic], storing them in byte sequence [buf], starting at
character number [pos].
It returns the actual number of characters read, between 0 and
[len] (inclusive).
@@ -784,15 +822,21 @@ val input : in_channel -> string -> int -> int -> int
if desired. (See also {!Pervasives.really_input} for reading
exactly [len] characters.)
Exception [Invalid_argument "input"] is raised if [pos] and [len]
- do not designate a valid substring of [buf]. *)
+ do not designate a valid range of [buf]. *)
-val really_input : in_channel -> string -> int -> int -> unit
+val really_input : in_channel -> bytes -> int -> int -> unit
(** [really_input ic buf pos len] reads [len] characters from channel [ic],
- storing them in string [buf], starting at character number [pos].
+ storing them in byte sequence [buf], starting at character number [pos].
Raise [End_of_file] if the end of file is reached before [len]
characters have been read.
Raise [Invalid_argument "really_input"] if
- [pos] and [len] do not designate a valid substring of [buf]. *)
+ [pos] and [len] do not designate a valid range of [buf]. *)
+
+val really_input_string : in_channel -> int -> string
+(** [really_input_string ic len] reads [len] characters from channel [ic]
+ and returns them in a new string.
+ Raise [End_of_file] if the end of file is reached before [len]
+ characters have been read. *)
val input_byte : in_channel -> int
(** Same as {!Pervasives.input_char}, but return the 8-bit integer representing
@@ -923,7 +967,7 @@ external decr : int ref -> unit = "%decr"
*)
(** Format strings have a general and highly polymorphic type
- [('a, 'b, 'c, 'd, 'e, 'f) format6]. Type [format6] is built in.
+ [('a, 'b, 'c, 'd, 'e, 'f) format6].
The two simplified types, [format] and [format4] below are
included for backward compatibility with earlier releases of
OCaml.
@@ -962,6 +1006,10 @@ external decr : int ref -> unit = "%decr"
for the [scanf]-style functions, it is typically the result type of the
receiver function.
*)
+
+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
@@ -1016,6 +1064,6 @@ val at_exit : (unit -> unit) -> unit
val valid_float_lexem : string -> string
-val unsafe_really_input : in_channel -> string -> int -> int -> unit
+val unsafe_really_input : in_channel -> bytes -> int -> int -> unit
val do_at_exit : unit -> unit
diff --git a/stdlib/printexc.ml b/stdlib/printexc.ml
index 285308b79d..4ebb84ceae 100644
--- a/stdlib/printexc.ml
+++ b/stdlib/printexc.ml
@@ -82,12 +82,13 @@ let catch fct arg =
eprintf "Uncaught exception: %s\n" (to_string x);
exit 2
-type raw_backtrace
+type raw_backtrace_slot
+type raw_backtrace = raw_backtrace_slot array
external get_raw_backtrace:
unit -> raw_backtrace = "caml_get_exception_raw_backtrace"
-type loc_info =
+type backtrace_slot =
| Known_location of bool (* is_raise *)
* string (* filename *)
* int (* line number *)
@@ -98,29 +99,27 @@ type loc_info =
(* to avoid warning *)
let _ = [Known_location (false, "", 0, 0, 0); Unknown_location false]
-type backtrace = loc_info array
+external convert_raw_backtrace_slot:
+ raw_backtrace_slot -> backtrace_slot = "caml_convert_raw_backtrace_slot"
-external convert_raw_backtrace:
- raw_backtrace -> backtrace option = "caml_convert_raw_backtrace"
+let convert_raw_backtrace rbckt =
+ try Some (Array.map convert_raw_backtrace_slot rbckt)
+ with Failure _ -> None
-let format_loc_info pos li =
- let is_raise =
- match li with
- | Known_location(is_raise, _, _, _, _) -> is_raise
- | Unknown_location(is_raise) -> is_raise in
- let info =
+let format_backtrace_slot pos slot =
+ let info is_raise =
if is_raise then
if pos = 0 then "Raised at" else "Re-raised at"
else
if pos = 0 then "Raised by primitive operation at" else "Called from"
in
- match li with
+ match slot with
+ | Unknown_location true -> (* compiler-inserted re-raise, skipped *) None
+ | Unknown_location false ->
+ Some (sprintf "%s unknown location" (info false))
| Known_location(is_raise, filename, lineno, startchar, endchar) ->
- sprintf "%s file \"%s\", line %d, characters %d-%d"
- info filename lineno startchar endchar
- | Unknown_location(is_raise) ->
- sprintf "%s unknown location"
- info
+ Some (sprintf "%s file \"%s\", line %d, characters %d-%d"
+ (info is_raise) filename lineno startchar endchar)
let print_exception_backtrace outchan backtrace =
match backtrace with
@@ -129,8 +128,9 @@ let print_exception_backtrace outchan backtrace =
"(Program not linked with -g, cannot print stack backtrace)\n"
| Some a ->
for i = 0 to Array.length a - 1 do
- if a.(i) <> Unknown_location true then
- fprintf outchan "%s\n" (format_loc_info i a.(i))
+ match format_backtrace_slot i a.(i) with
+ | None -> ()
+ | Some str -> fprintf outchan "%s\n" str
done
let print_raw_backtrace outchan raw_backtrace =
@@ -147,20 +147,70 @@ let backtrace_to_string backtrace =
| Some a ->
let b = Buffer.create 1024 in
for i = 0 to Array.length a - 1 do
- if a.(i) <> Unknown_location true then
- bprintf b "%s\n" (format_loc_info i a.(i))
+ match format_backtrace_slot i a.(i) with
+ | None -> ()
+ | Some str -> bprintf b "%s\n" str
done;
Buffer.contents b
let raw_backtrace_to_string raw_backtrace =
backtrace_to_string (convert_raw_backtrace raw_backtrace)
+let backtrace_slot_is_raise = function
+ | Known_location(is_raise, _, _, _, _) -> is_raise
+ | Unknown_location(is_raise) -> is_raise
+
+type location = {
+ filename : string;
+ line_number : int;
+ start_char : int;
+ end_char : int;
+}
+
+let backtrace_slot_location = function
+ | Unknown_location _ -> None
+ | Known_location(_is_raise, filename, line_number,
+ start_char, end_char) ->
+ Some {
+ filename;
+ line_number;
+ start_char;
+ end_char;
+ }
+
+let backtrace_slots raw_backtrace =
+ (* The documentation of this function guarantees that Some is
+ returned only if a part of the trace is usable. This gives us
+ a bit more work than just convert_raw_backtrace, but it makes the
+ API more user-friendly -- otherwise most users would have to
+ reimplement the "Program not linked with -g, sorry" logic
+ themselves. *)
+ match convert_raw_backtrace raw_backtrace with
+ | None -> None
+ | Some backtrace ->
+ let usable_slot = function
+ | Unknown_location _ -> false
+ | Known_location _ -> true in
+ let rec exists_usable = function
+ | (-1) -> false
+ | i -> usable_slot backtrace.(i) || exists_usable (i - 1) in
+ if exists_usable (Array.length backtrace - 1)
+ then Some backtrace
+ else None
+
+module Slot = struct
+ type t = backtrace_slot
+ let format = format_backtrace_slot
+ let is_raise = backtrace_slot_is_raise
+ let location = backtrace_slot_location
+end
+
+let raw_backtrace_length bckt = Array.length bckt
+let get_raw_backtrace_slot bckt i = Array.get bckt i
+
(* confusingly named:
returns the *string* corresponding to the global current backtrace *)
let get_backtrace () =
- (* we could use the caml_get_exception_backtrace primitive here, but
- we hope to deprecate it so it's better to just compose the
- raw stuff *)
backtrace_to_string (convert_raw_backtrace (get_raw_backtrace ()))
external record_backtrace: bool -> unit = "caml_record_backtrace"
@@ -169,10 +219,8 @@ external backtrace_status: unit -> bool = "caml_backtrace_status"
let register_printer fn =
printers := fn :: !printers
-
external get_callstack: int -> raw_backtrace = "caml_get_current_callstack"
-
let exn_slot x =
let x = Obj.repr x in
if Obj.tag x = 0 then Obj.field x 0 else x
diff --git a/stdlib/printexc.mli b/stdlib/printexc.mli
index 2916bf1435..6bffe174cb 100644
--- a/stdlib/printexc.mli
+++ b/stdlib/printexc.mli
@@ -86,19 +86,53 @@ val register_printer: (exn -> string option) -> unit
(** {6 Raw backtraces} *)
type raw_backtrace
-
-(** The abstract type [backtrace] stores exception backtraces in
+(** The abstract type [raw_backtrace] stores a backtrace in
a low-level format, instead of directly exposing them as string as
the [get_backtrace()] function does.
This allows delaying the formatting of backtraces to when they are
- actually printed, which might be useful if you record more
+ actually printed, which may be useful if you record more
backtraces than you print.
+
+ Raw backtraces cannot be marshalled. If you need marshalling, you
+ should use the array returned by the [backtrace_slots] function of
+ the next section.
+
+ @since 4.01.0
*)
val get_raw_backtrace: unit -> raw_backtrace
+(** [Printexc.get_raw_backtrace ()] returns the same exception
+ backtrace that [Printexc.print_backtrace] would print, but in
+ a raw format.
+
+ @since 4.01.0
+*)
+
val print_raw_backtrace: out_channel -> raw_backtrace -> unit
+(** Print a raw backtrace in the same format
+ [Printexc.print_backtrace] uses.
+
+ @since 4.01.0
+*)
+
val raw_backtrace_to_string: raw_backtrace -> string
+(** Return a string from a raw backtrace, in the same format
+ [Printexc.get_backtrace] uses.
+
+ @since 4.01.0
+*)
+
+(** {6 Current call stack} *)
+
+val get_callstack: int -> raw_backtrace
+(** [Printexc.get_callstack n] returns a description of the top of the
+ call stack on the current program point (for the current thread),
+ with at most [n] entries. (Note: this function is not related to
+ exceptions at all, despite being part of the [Printexc] module.)
+
+ @since 4.01.0
+*)
(** {6 Uncaught exceptions} *)
@@ -116,16 +150,120 @@ val set_uncaught_exception_handler: (exn -> raw_backtrace -> unit) -> unit
@since 4.02.0
*)
-(** {6 Current call stack} *)
-val get_callstack: int -> raw_backtrace
+(** {6 Manipulation of backtrace information}
-(** [Printexc.get_callstack n] returns a description of the top of the
- call stack on the current program point (for the current thread),
- with at most [n] entries. (Note: this function is not related to
- exceptions at all, despite being part of the [Printexc] module.)
+ Those function allow to traverse the slots of a raw backtrace,
+ extract information from them in a programmer-friendly format.
+*)
- @since 4.01.0
+type backtrace_slot
+(** The abstract type [backtrace_slot] represents a single slot of
+ a backtrace.
+
+ @since 4.02
+*)
+
+val backtrace_slots : raw_backtrace -> backtrace_slot array option
+(** Returns the slots of a raw backtrace, or [None] if none of them
+ contain useful information.
+
+ In the return array, the slot at index [0] corresponds to the most
+ recent function call, raise, or primitive [get_backtrace] call in
+ the trace.
+
+ Some possible reasons for returning [None] are as follow:
+ - none of the slots in the trace come from modules compiled with
+ debug information ([-g])
+ - the program is a bytecode program that has not been linked with
+ debug information enabled ([ocamlc -g])
+*)
+
+type location = {
+ filename : string;
+ line_number : int;
+ start_char : int;
+ end_char : int;
+}
+(** The type of location information found in backtraces. [start_char]
+ and [end_char] are positions relative to the beginning of the
+ line.
+
+ @since 4.02
+*)
+
+module Slot : sig
+ type t = backtrace_slot
+
+ val is_raise : t -> bool
+ (** [is_raise slot] is [true] when [slot] refers to a raising
+ point in the code, and [false] when it comes from a simple
+ function call.
+
+ @since 4.02
+ *)
+
+ val location : t -> location option
+ (** [location slot] returns the location information of the slot,
+ if available, and [None] otherwise.
+
+ Some possible reasons for failing to return a location are as follow:
+ - the slot corresponds to a compiler-inserted raise
+ - the slot corresponds to a part of the program that has not been
+ compiled with debug information ([-g])
+
+ @since 4.02
+ *)
+
+ val format : int -> t -> string option
+ (** [format pos slot] returns the string representation of [slot] as
+ [raw_backtrace_to_string] would format it, assuming it is the
+ [pos]-th element of the backtrace: the [0]-th element is
+ pretty-printed differently than the others.
+
+ Whole-backtrace printing functions also skip some uninformative
+ slots; in that case, [format pos slot] returns [None].
+
+ @since 4.02
+ *)
+end
+
+
+(** {6 Raw backtrace slots} *)
+
+type raw_backtrace_slot
+(** This type allows direct access to raw backtrace slots, without any
+ conversion in an OCaml-usable data-structure. Being
+ process-specific, they must absolutely not be marshalled, and are
+ unsafe to use for this reason (marshalling them may not fail, but
+ un-marshalling and using the result will result in
+ undefined behavior).
+
+ Elements of this type can still be compared and hashed: when two
+ elements are equal, then they represent the same source location
+ (the converse is not necessarily true in presence of inlining,
+ for example).
+*)
+
+val raw_backtrace_length : raw_backtrace -> int
+(** [raw_backtrace_length bckt] returns the number of slots in the
+ backtrace [bckt].
+
+ @since 4.02
+*)
+
+val get_raw_backtrace_slot : raw_backtrace -> int -> raw_backtrace_slot
+(** [get_slot bckt pos] returns the slot in position [pos] in the
+ backtrace [bckt].
+
+ @since 4.02
+*)
+
+val convert_raw_backtrace_slot : raw_backtrace_slot -> backtrace_slot
+(** Extracts the user-friendly [backtrace_slot] from a low-level
+ [raw_backtrace_slot].
+
+ @since 4.02
*)
diff --git a/stdlib/printf.ml b/stdlib/printf.ml
index 3801692047..1152429f9a 100644
--- a/stdlib/printf.ml
+++ b/stdlib/printf.ml
@@ -11,728 +11,29 @@
(* *)
(***********************************************************************)
-external format_float: string -> float -> string
- = "caml_format_float"
-external format_int: string -> int -> string
- = "caml_format_int"
-external format_int32: string -> int32 -> string
- = "caml_int32_format"
-external format_nativeint: string -> nativeint -> string
- = "caml_nativeint_format"
-external format_int64: string -> int64 -> string
- = "caml_int64_format"
-
-module Sformat = struct
-
- type index;;
-
- external unsafe_index_of_int : int -> index = "%identity"
- ;;
- let index_of_int i =
- if i >= 0 then unsafe_index_of_int i
- else failwith ("Sformat.index_of_int: negative argument " ^ string_of_int i)
- ;;
- external int_of_index : index -> int = "%identity"
- ;;
-
- let add_int_index i idx = index_of_int (i + int_of_index idx);;
- let succ_index = add_int_index 1;;
- (* Literal position are one-based (hence pred p instead of p). *)
- let index_of_literal_position p = index_of_int (pred p);;
-
- external length : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> int
- = "%string_length"
- ;;
- external get : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> int -> char
- = "%string_safe_get"
- ;;
- external unsafe_get : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> int -> char
- = "%string_unsafe_get"
- ;;
- external unsafe_to_string : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> string
- = "%identity"
- ;;
- let sub fmt idx len =
- String.sub (unsafe_to_string fmt) (int_of_index idx) len
- ;;
- let to_string fmt = sub fmt (unsafe_index_of_int 0) (length fmt)
- ;;
-
-end
-;;
-
-let bad_conversion sfmt i c =
- invalid_arg
- ("Printf: bad conversion %" ^ String.make 1 c ^ ", at char number " ^
- string_of_int i ^ " in format string \'" ^ sfmt ^ "\'")
-;;
-
-let bad_conversion_format fmt i c =
- bad_conversion (Sformat.to_string fmt) i c
-;;
-
-let incomplete_format fmt =
- invalid_arg
- ("Printf: premature end of format string \'" ^
- Sformat.to_string fmt ^ "\'")
-;;
-
-(* Parses a string conversion to return the specified length and the
- padding direction. *)
-let parse_string_conversion sfmt =
- let rec parse neg i =
- if i >= String.length sfmt then (0, neg) else
- match String.unsafe_get sfmt i with
- | '1'..'9' ->
- (int_of_string
- (String.sub sfmt i (String.length sfmt - i - 1)),
- neg)
- | '-' ->
- parse true (succ i)
- | _ ->
- parse neg (succ i) in
- try parse false 1 with
- | Failure _ -> bad_conversion sfmt 0 's'
-;;
-
-(* Pad a (sub) string into a blank string of length [p],
- on the right if [neg] is true, on the left otherwise. *)
-let pad_string pad_char p neg s i len =
- if p = len && i = 0 then s else
- if p <= len then String.sub s i len else
- let res = String.make p pad_char in
- if neg
- then String.blit s i res 0 len
- else String.blit s i res (p - len) len;
- res
-;;
-
-(* Format a string given a %s format, e.g. %40s or %-20s.
- To do ?: ignore other flags (#, +, etc). *)
-let format_string sfmt s =
- let (p, neg) = parse_string_conversion sfmt in
- pad_string ' ' p neg s 0 (String.length s)
-;;
-
-(* Extract a format string out of [fmt] between [start] and [stop] inclusive.
- ['*'] in the format are replaced by integers taken from the [widths] list.
- [extract_format] returns a string which is the string representation of
- the resulting format string. *)
-let extract_format fmt start stop widths =
- let skip_positional_spec start =
- match Sformat.unsafe_get fmt start with
- | '0'..'9' ->
- let rec skip_int_literal i =
- match Sformat.unsafe_get fmt i with
- | '0'..'9' -> skip_int_literal (succ i)
- | '$' -> succ i
- | _ -> start in
- skip_int_literal (succ start)
- | _ -> start in
- let start = skip_positional_spec (succ start) in
- let b = Buffer.create (stop - start + 10) in
- Buffer.add_char b '%';
- let rec fill_format i widths =
- if i <= stop then
- match (Sformat.unsafe_get fmt i, widths) with
- | ('*', h :: t) ->
- Buffer.add_string b (string_of_int h);
- let i = skip_positional_spec (succ i) in
- fill_format i t
- | ('*', []) ->
- assert false (* Should not happen since this is ill-typed. *)
- | (c, _) ->
- Buffer.add_char b c;
- fill_format (succ i) widths in
- fill_format start (List.rev widths);
- Buffer.contents b
-;;
-
-let extract_format_int conv fmt start stop widths =
- let sfmt = extract_format fmt start stop widths in
- match conv with
- | 'n' | 'N' ->
- sfmt.[String.length sfmt - 1] <- 'u';
- sfmt
- | _ -> sfmt
-;;
-
-let extract_format_float conv fmt start stop widths =
- let sfmt = extract_format fmt start stop widths in
- match conv with
- | 'F' ->
- sfmt.[String.length sfmt - 1] <- 'g';
- sfmt
- | _ -> sfmt
-;;
-
-(* Returns the position of the next character following the meta format
- string, starting from position [i], inside a given format [fmt].
- According to the character [conv], the meta format string is
- enclosed by the delimiters %{ and %} (when [conv = '{']) or %( and
- %) (when [conv = '(']). Hence, [sub_format] returns the index of
- the character following the [')'] or ['}'] that ends the meta format,
- according to the character [conv]. *)
-let sub_format incomplete_format bad_conversion_format conv fmt i =
- let len = Sformat.length fmt in
- let rec sub_fmt c i =
- let close = if c = '(' then ')' else (* '{' *) '}' in
- let rec sub j =
- if j >= len then incomplete_format fmt else
- match Sformat.get fmt j with
- | '%' -> sub_sub (succ j)
- | _ -> sub (succ j)
- and sub_sub j =
- if j >= len then incomplete_format fmt else
- match Sformat.get fmt j with
- | '(' | '{' as c ->
- let j = sub_fmt c (succ j) in
- sub (succ j)
- | '}' | ')' as c ->
- if c = close then succ j else bad_conversion_format fmt i c
- | _ -> sub (succ j) in
- sub i in
- sub_fmt conv i
-;;
-
-let sub_format_for_printf conv =
- sub_format incomplete_format bad_conversion_format conv
-;;
-
-let iter_on_format_args fmt add_conv add_char =
-
- let lim = Sformat.length fmt - 1 in
-
- let rec scan_flags skip i =
- if i > lim then incomplete_format fmt else
- match Sformat.unsafe_get fmt i with
- | '*' -> scan_flags skip (add_conv skip i 'i')
- (* | '$' -> scan_flags skip (succ i) *** PR#4321 *)
- | '#' | '-' | ' ' | '+' -> scan_flags skip (succ i)
- | '_' -> scan_flags true (succ i)
- | '0'..'9'
- | '.' -> scan_flags skip (succ i)
- | _ -> scan_conv skip i
- and scan_conv skip i =
- if i > lim then incomplete_format fmt else
- match Sformat.unsafe_get fmt i with
- | '%' | '@' | '!' | ',' -> succ i
- | 's' | 'S' | '[' -> add_conv skip i 's'
- | 'c' | 'C' -> add_conv skip i 'c'
- | 'd' | 'i' |'o' | 'u' | 'x' | 'X' | 'N' -> add_conv skip i 'i'
- | 'f' | 'e' | 'E' | 'g' | 'G' | 'F' -> add_conv skip i 'f'
- | 'B' | 'b' -> add_conv skip i 'B'
- | 'a' | 'r' | 't' as conv -> add_conv skip i conv
- | 'l' | 'n' | 'L' as conv ->
- let j = succ i in
- if j > lim then add_conv skip i 'i' else begin
- match Sformat.get fmt j with
- | 'd' | 'i' | 'o' | 'u' | 'x' | 'X' ->
- add_char (add_conv skip i conv) 'i'
- | _ -> add_conv skip i 'i' end
- | '{' as conv ->
- (* Just get a regular argument, skipping the specification. *)
- let i = add_conv skip i conv in
- (* To go on, find the index of the next char after the meta format. *)
- let j = sub_format_for_printf conv fmt i in
- (* Add the meta specification to the summary anyway. *)
- let rec loop i =
- if i < j - 2 then loop (add_char i (Sformat.get fmt i)) in
- loop i;
- (* Go on, starting at the closing brace to properly close the meta
- specification in the summary. *)
- scan_conv skip (j - 1)
- | '(' as conv ->
- (* Use the static format argument specification instead of
- the runtime format argument value: they must have the same type
- anyway. *)
- scan_fmt (add_conv skip i conv)
- | '}' | ')' as conv -> add_conv skip i conv
- | conv -> bad_conversion_format fmt i conv
-
- and scan_fmt i =
- if i < lim then
- if Sformat.get fmt i = '%'
- then scan_fmt (scan_flags false (succ i))
- else scan_fmt (succ i)
- else i in
-
- ignore (scan_fmt 0)
-;;
-
-(* Returns a string that summarizes the typing information that a given
- format string contains.
- For instance, [summarize_format_type "A number %d\n"] is "%i".
- It also checks the well-formedness of the format string. *)
-let summarize_format_type fmt =
- let len = Sformat.length fmt in
- let b = Buffer.create len in
- let add_char i c = Buffer.add_char b c; succ i in
- let add_conv skip i c =
- if skip then Buffer.add_string b "%_" else Buffer.add_char b '%';
- add_char i c in
- iter_on_format_args fmt add_conv add_char;
- Buffer.contents b
-;;
-
-module Ac = struct
- type ac = {
- mutable ac_rglr : int;
- mutable ac_skip : int;
- mutable ac_rdrs : int;
- }
-end
-;;
-
-open Ac;;
-
-(* Computes the number of arguments of a format (including the flag
- arguments if any). *)
-let ac_of_format fmt =
- let ac = { ac_rglr = 0; ac_skip = 0; ac_rdrs = 0; } in
- let incr_ac skip c =
- let inc = if c = 'a' then 2 else 1 in
- if c = 'r' then ac.ac_rdrs <- ac.ac_rdrs + 1;
- if skip
- then ac.ac_skip <- ac.ac_skip + inc
- else ac.ac_rglr <- ac.ac_rglr + inc in
- let add_conv skip i c =
- (* Just finishing a meta format: no additional argument to record. *)
- if c <> ')' && c <> '}' then incr_ac skip c;
- succ i
- and add_char i _ = succ i in
-
- iter_on_format_args fmt add_conv add_char;
- ac
-;;
-
-let count_printing_arguments_of_format fmt =
- let ac = ac_of_format fmt in
- (* For printing, only the regular arguments have to be counted. *)
- ac.ac_rglr
-;;
-
-let list_iter_i f l =
- let rec loop i = function
- | [] -> ()
- | [x] -> f i x (* Tail calling [f] *)
- | x :: xs -> f i x; loop (succ i) xs in
- loop 0 l
-;;
-
-(* 'Abstracting' version of kprintf: returns a (curried) function that
- will print when totally applied.
- Note: in the following, we are careful not to be badly caught
- by the compiler optimizations for the representation of arrays. *)
-let kapr kpr fmt =
- match count_printing_arguments_of_format fmt with
- | 0 -> kpr fmt [||]
- | 1 -> Obj.magic (fun x ->
- let a = Array.make 1 (Obj.repr 0) in
- a.(0) <- x;
- kpr fmt a)
- | 2 -> Obj.magic (fun x y ->
- let a = Array.make 2 (Obj.repr 0) in
- a.(0) <- x; a.(1) <- y;
- kpr fmt a)
- | 3 -> Obj.magic (fun x y z ->
- let a = Array.make 3 (Obj.repr 0) in
- a.(0) <- x; a.(1) <- y; a.(2) <- z;
- kpr fmt a)
- | 4 -> Obj.magic (fun x y z t ->
- let a = Array.make 4 (Obj.repr 0) in
- a.(0) <- x; a.(1) <- y; a.(2) <- z;
- a.(3) <- t;
- kpr fmt a)
- | 5 -> Obj.magic (fun x y z t u ->
- let a = Array.make 5 (Obj.repr 0) in
- a.(0) <- x; a.(1) <- y; a.(2) <- z;
- a.(3) <- t; a.(4) <- u;
- kpr fmt a)
- | 6 -> Obj.magic (fun x y z t u v ->
- let a = Array.make 6 (Obj.repr 0) in
- a.(0) <- x; a.(1) <- y; a.(2) <- z;
- a.(3) <- t; a.(4) <- u; a.(5) <- v;
- kpr fmt a)
- | nargs ->
- let rec loop i args =
- if i >= nargs then
- let a = Array.make nargs (Obj.repr 0) in
- list_iter_i (fun i arg -> a.(nargs - i - 1) <- arg) args;
- kpr fmt a
- else Obj.magic (fun x -> loop (succ i) (x :: args)) in
- loop 0 []
-;;
-
-type positional_specification =
- | Spec_none | Spec_index of Sformat.index
-;;
-
-(* To scan an optional positional parameter specification,
- i.e. an integer followed by a [$].
-
- Calling [got_spec] with appropriate arguments, we 'return' a positional
- specification and an index to go on scanning the [fmt] format at hand.
-
- Note that this is optimized for the regular case, i.e. no positional
- parameter, since in this case we juste 'return' the constant
- [Spec_none]; in case we have a positional parameter, we 'return' a
- [Spec_index] [positional_specification] which is a bit more costly.
-
- Note also that we do not support [*$] specifications, since this would
- lead to type checking problems: a [*$] positional specification means
- 'take the next argument to [printf] (which must be an integer value)',
- name this integer value $n$; [*$] now designates parameter $n$.
-
- Unfortunately, the type of a parameter specified via a [*$] positional
- specification should be the type of the corresponding argument to
- [printf], hence this should be the type of the $n$-th argument to [printf]
- with $n$ being the {\em value} of the integer argument defining [*]; we
- clearly cannot statically guess the value of this parameter in the general
- case. Put it another way: this means type dependency, which is completely
- out of scope of the OCaml type algebra. *)
-
-let scan_positional_spec fmt got_spec i =
- match Sformat.unsafe_get fmt i with
- | '0'..'9' as d ->
- let rec get_int_literal accu j =
- match Sformat.unsafe_get fmt j with
- | '0'..'9' as d ->
- get_int_literal (10 * accu + (int_of_char d - 48)) (succ j)
- | '$' ->
- if accu = 0 then
- failwith "printf: bad positional specification (0)." else
- got_spec (Spec_index (Sformat.index_of_literal_position accu)) (succ j)
- (* Not a positional specification: tell so the caller, and go back to
- scanning the format from the original [i] position we were called at
- first. *)
- | _ -> got_spec Spec_none i in
- get_int_literal (int_of_char d - 48) (succ i)
- (* No positional specification: tell so the caller, and go back to scanning
- the format from the original [i] position. *)
- | _ -> got_spec Spec_none i
-;;
-
-(* Get the index of the next argument to printf, according to the given
- positional specification. *)
-let next_index spec n =
- match spec with
- | Spec_none -> Sformat.succ_index n
- | Spec_index _ -> n
-;;
-
-(* Get the index of the actual argument to printf, according to its
- optional positional specification. *)
-let get_index spec n =
- match spec with
- | Spec_none -> n
- | Spec_index p -> p
-;;
-
-(* Format a float argument as a valid OCaml lexeme. *)
-let format_float_lexeme =
-
- (* To be revised: this procedure should be a unique loop that performs the
- validity check and the string lexeme modification at the same time.
- Otherwise, it is too difficult to handle the strange padding facilities
- given by printf. Let alone handling the correct widths indication,
- knowing that we have sometime to add a '.' at the end of the result!
- *)
-
- let make_valid_float_lexeme s =
- (* Check if s is already a valid lexeme:
- in this case do nothing,
- otherwise turn s into a valid OCaml lexeme. *)
- let l = String.length s in
- let rec valid_float_loop i =
- if i >= l then s ^ "." else
- match s.[i] with
- (* Sure, this is already a valid float lexeme. *)
- | '.' | 'e' | 'E' -> s
- | _ -> valid_float_loop (i + 1) in
-
- valid_float_loop 0 in
-
- (fun sfmt x ->
- match classify_float x with
- | FP_normal | FP_subnormal | FP_zero ->
- make_valid_float_lexeme (format_float sfmt x)
- | FP_infinite ->
- if x < 0.0 then "neg_infinity" else "infinity"
- | FP_nan ->
- "nan")
-;;
-
-(* Decode a format string and act on it.
- [fmt] is the [printf] format string, and [pos] points to a [%] character in
- the format string.
- After consuming the appropriate number of arguments and formatting
- them, one of the following five continuations described below is called:
-
- - [cont_s] for outputting a string
- (arguments: arg num, string, next pos)
- - [cont_a] for performing a %a action
- (arguments: arg num, fn, arg, next pos)
- - [cont_t] for performing a %t action
- (arguments: arg num, fn, next pos)
- - [cont_f] for performing a flush action
- (arguments: arg num, next pos)
- - [cont_m] for performing a %( action
- (arguments: arg num, sfmt, next pos)
-
- "arg num" is the index in array [args] of the next argument to [printf].
- "next pos" is the position in [fmt] of the first character following
- the %conversion specification in [fmt]. *)
-
-(* Note: here, rather than test explicitly against [Sformat.length fmt]
- to detect the end of the format, we use [Sformat.unsafe_get] and
- rely on the fact that we'll get a "null" character if we access
- one past the end of the string. These "null" characters are then
- caught by the [_ -> bad_conversion] clauses below.
- Don't do this at home, kids. *)
-let scan_format fmt args n pos cont_s cont_a cont_t cont_f cont_m =
-
- let get_arg spec n =
- Obj.magic (args.(Sformat.int_of_index (get_index spec n))) in
-
- let rec scan_positional n widths i =
- let got_spec spec i = scan_flags spec n widths i in
- scan_positional_spec fmt got_spec i
-
- and scan_flags spec n widths i =
- match Sformat.unsafe_get fmt i with
- | '*' ->
- let got_spec wspec i =
- let (width : int) = get_arg wspec n in
- scan_flags spec (next_index wspec n) (width :: widths) i in
- scan_positional_spec fmt got_spec (succ i)
- | '0'..'9'
- | '.' | '#' | '-' | ' ' | '+' -> scan_flags spec n widths (succ i)
- | _ -> scan_conv spec n widths i
-
- and scan_conv spec n widths i =
- match Sformat.unsafe_get fmt i with
- | '%' | '@' as c ->
- cont_s n (String.make 1 c) (succ i)
- | '!' -> cont_f n (succ i)
- | ',' -> cont_s n "" (succ i)
- | 's' | 'S' as conv ->
- let (x : string) = get_arg spec n in
- let x = if conv = 's' then x else "\"" ^ String.escaped x ^ "\"" in
- let s =
- (* Optimize for common case %s *)
- if i = succ pos then x else
- format_string (extract_format fmt pos i widths) x in
- cont_s (next_index spec n) s (succ i)
- | '[' as conv ->
- bad_conversion_format fmt i conv
- | 'c' | 'C' as conv ->
- let (x : char) = get_arg spec n in
- let s =
- if conv = 'c' then String.make 1 x else "'" ^ Char.escaped x ^ "'" in
- cont_s (next_index spec n) s (succ i)
- | 'd' | 'i' | 'o' | 'u' | 'x' | 'X' | 'N' as conv ->
- let (x : int) = get_arg spec n in
- let s =
- format_int (extract_format_int conv fmt pos i widths) x in
- cont_s (next_index spec n) s (succ i)
- | 'f' | 'e' | 'E' | 'g' | 'G' ->
- let (x : float) = get_arg spec n in
- let s = format_float (extract_format fmt pos i widths) x in
- cont_s (next_index spec n) s (succ i)
- | 'F' as conv ->
- let (x : float) = get_arg spec n in
- let s =
- format_float_lexeme
- (if widths = []
- then "%.12g"
- else extract_format_float conv fmt pos i widths)
- x in
- cont_s (next_index spec n) s (succ i)
- | 'B' | 'b' ->
- let (x : bool) = get_arg spec n in
- cont_s (next_index spec n) (string_of_bool x) (succ i)
- | 'a' ->
- let printer = get_arg spec n in
- (* If the printer spec is Spec_none, go on as usual.
- If the printer spec is Spec_index p,
- printer's argument spec is Spec_index (succ_index p). *)
- let n = Sformat.succ_index (get_index spec n) in
- let arg = get_arg Spec_none n in
- cont_a (next_index spec n) printer arg (succ i)
- | 'r' as conv ->
- bad_conversion_format fmt i conv
- | 't' ->
- let printer = get_arg spec n in
- cont_t (next_index spec n) printer (succ i)
- | 'l' | 'n' | 'L' as conv ->
- begin match Sformat.unsafe_get fmt (succ i) with
- | 'd' | 'i' | 'o' | 'u' | 'x' | 'X' ->
- let i = succ i in
- let s =
- match conv with
- | 'l' ->
- let (x : int32) = get_arg spec n in
- format_int32 (extract_format fmt pos i widths) x
- | 'n' ->
- let (x : nativeint) = get_arg spec n in
- format_nativeint (extract_format fmt pos i widths) x
- | _ ->
- let (x : int64) = get_arg spec n in
- format_int64 (extract_format fmt pos i widths) x in
- cont_s (next_index spec n) s (succ i)
- | _ ->
- let (x : int) = get_arg spec n in
- let s = format_int (extract_format_int 'n' fmt pos i widths) x in
- cont_s (next_index spec n) s (succ i)
- end
- | '{' | '(' as conv (* ')' '}' *) ->
- let (xf : ('a, 'b, 'c, 'd, 'e, 'f) format6) = get_arg spec n in
- let i = succ i in
- let i = sub_format_for_printf conv fmt i in
- if conv = '{' (* '}' *) then
- (* Just print the format argument as a specification. *)
- cont_s
- (next_index spec n)
- (summarize_format_type xf)
- i else
- (* Use the format argument instead of the format specification. *)
- cont_m (next_index spec n) xf i
- | (* '(' *) ')' ->
- cont_s n "" (succ i)
- | conv ->
- bad_conversion_format fmt i conv in
-
- scan_positional n [] (succ pos)
-;;
-
-let mkprintf to_s get_out outc outs flush k fmt =
-
- (* [out] is global to this definition of [pr], and must be shared by all its
- recursive calls (if any). *)
- let out = get_out fmt in
- let outc c = outc out c in
- let outs s = outs out s in
-
- let rec pr k n fmt v =
-
- let len = Sformat.length fmt in
-
- let rec doprn n i =
- if i >= len then Obj.magic (k out) else
- match Sformat.unsafe_get fmt i with
- | '%' -> scan_format fmt v n i cont_s cont_a cont_t cont_f cont_m
- | c -> outc c; doprn n (succ i)
-
- and cont_s n s i =
- outs s; doprn n i
- and cont_a n printer arg i =
- if to_s then
- outs ((Obj.magic printer : unit -> _ -> string) () arg)
- else
- printer out arg;
- doprn n i
- and cont_t n printer i =
- if to_s then
- outs ((Obj.magic printer : unit -> string) ())
- else
- printer out;
- doprn n i
- and cont_f n i =
- flush out; doprn n i
- and cont_m n xf i =
- let m =
- Sformat.add_int_index
- (count_printing_arguments_of_format xf) n in
- pr (Obj.magic (fun _ -> doprn m i)) n xf v in
-
- doprn n 0 in
-
- let kpr = pr k (Sformat.index_of_int 0) in
-
- kapr kpr fmt
-;;
-
-(**************************************************************
-
- Defining [fprintf] and various flavors of [fprintf].
-
- **************************************************************)
-
-let kfprintf k oc =
- mkprintf false (fun _ -> oc) output_char output_string flush k
-;;
-let ikfprintf k oc = kapr (fun _ _ -> Obj.magic (k oc));;
-
-let fprintf oc = kfprintf ignore oc;;
-let ifprintf oc = ikfprintf ignore oc;;
-let printf fmt = fprintf stdout fmt;;
-let eprintf fmt = fprintf stderr fmt;;
-
-let kbprintf k b =
- mkprintf false (fun _ -> b) Buffer.add_char Buffer.add_string ignore k
-;;
-let bprintf b = kbprintf ignore b;;
-
-let get_buff fmt =
- let len = 2 * Sformat.length fmt in
- Buffer.create len
-;;
-
-let get_contents b =
- let s = Buffer.contents b in
- Buffer.clear b;
- s
-;;
-
-let get_cont k b = k (get_contents b);;
-
-let ksprintf k =
- mkprintf true get_buff Buffer.add_char Buffer.add_string ignore (get_cont k)
-;;
-
-let sprintf fmt = ksprintf (fun s -> s) fmt;;
-
-(**************************************************************
-
- Deprecated stuff.
-
- **************************************************************)
-
-let kprintf = ksprintf;;
-
-(* For OCaml system internal use only: needed to implement modules [Format]
- and [Scanf]. *)
-
-module CamlinternalPr = struct
-
- module Sformat = Sformat;;
-
- module Tformat = struct
-
- type ac =
- Ac.ac = {
- mutable ac_rglr : int;
- mutable ac_skip : int;
- mutable ac_rdrs : int;
- }
- ;;
-
- let ac_of_format = ac_of_format;;
-
- let count_printing_arguments_of_format =
- count_printing_arguments_of_format;;
-
- let sub_format = sub_format;;
-
- let summarize_format_type = summarize_format_type;;
-
- let scan_format = scan_format;;
-
- let kapr = kapr;;
-
- end
- ;;
-
-end
-;;
+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
+let kbprintf k b (Format (fmt, _)) =
+ make_printf (fun b acc -> bufput_acc b acc; k b) b End_of_acc fmt
+let ikfprintf k oc (Format (fmt, _)) =
+ make_printf (fun oc _ -> k oc) oc End_of_acc fmt
+
+let fprintf oc fmt = kfprintf ignore oc fmt
+let bprintf b fmt = kbprintf ignore b fmt
+let ifprintf oc fmt = ikfprintf ignore oc fmt
+let printf fmt = fprintf stdout fmt
+let eprintf fmt = fprintf stderr fmt
+
+let ksprintf k (Format (fmt, _)) =
+ 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
+
+let sprintf fmt = ksprintf (fun s -> s) fmt
+
+let kprintf = ksprintf
diff --git a/stdlib/printf.mli b/stdlib/printf.mli
index a75a64181d..21e28159af 100644
--- a/stdlib/printf.mli
+++ b/stdlib/printf.mli
@@ -163,76 +163,5 @@ val kbprintf : (Buffer.t -> 'a) -> Buffer.t ->
(** Deprecated *)
-val kprintf : (string -> 'a) -> ('b, unit, string, 'a) format4 -> 'b;;
+val kprintf : (string -> 'a) -> ('b, unit, string, 'a) format4 -> 'b
(** A deprecated synonym for [ksprintf]. *)
-
-(**/**)
-
-(* The following is for system use only. Do not call directly. *)
-
-module CamlinternalPr : sig
-
- module Sformat : sig
- type index;;
-
- val index_of_int : int -> index;;
- external int_of_index : index -> int = "%identity";;
- external unsafe_index_of_int : int -> index = "%identity";;
-
- val succ_index : index -> index;;
- val add_int_index : int -> index -> index;;
-
- val sub : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> index -> int -> string;;
- val to_string : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> string;;
- external length : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> int
- = "%string_length";;
- external get : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> int -> char
- = "%string_safe_get";;
- external unsafe_to_string : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> string
- = "%identity";;
- external unsafe_get : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> int -> char
- = "%string_unsafe_get";;
-
- end;;
-
- module Tformat : sig
-
- type ac = {
- mutable ac_rglr : int;
- mutable ac_skip : int;
- mutable ac_rdrs : int;
- };;
-
- val ac_of_format : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> ac;;
- val count_printing_arguments_of_format :
- ('a, 'b, 'c, 'd, 'e, 'f) format6 -> int;;
-
- val sub_format :
- (('a, 'b, 'c, 'd, 'e, 'f) format6 -> int) ->
- (('a, 'b, 'c, 'd, 'e, 'f) format6 -> int -> char -> int) ->
- char ->
- ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
- int ->
- int
-
- val summarize_format_type : ('a, 'b, 'c, 'd, 'e, 'f) format6 -> string
-
- val scan_format : ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
- 'g array ->
- Sformat.index ->
- int ->
- (Sformat.index -> string -> int -> 'h) ->
- (Sformat.index -> 'i -> 'j -> int -> 'h) ->
- (Sformat.index -> 'k -> int -> 'h) ->
- (Sformat.index -> int -> 'h) ->
- (Sformat.index -> ('l, 'm, 'n, 'o, 'p, 'q) format6 -> int -> 'h) ->
- 'h
-
- val kapr :
- (('a, 'b, 'c, 'd, 'e, 'f) format6 -> Obj.t array -> 'g) ->
- ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
- 'g
-
- end;;
-
-end;;
diff --git a/stdlib/scanf.ml b/stdlib/scanf.ml
index 8f694fd3a2..c21de72484 100644
--- a/stdlib/scanf.ml
+++ b/stdlib/scanf.ml
@@ -11,6 +11,19 @@
(* *)
(***********************************************************************)
+open CamlinternalFormatBasics
+open CamlinternalFormat
+
+(* alias to avoid warning for ambiguity between
+ Pervasives.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
+
(* The run-time library for scanners. *)
(* Scanning buffers. *)
@@ -318,17 +331,17 @@ module Scanning : SCANNING = struct
let from_ic scan_close_ic iname ic =
let len = !file_buffer_size in
- let buf = String.create len in
+ let buf = Bytes.create len in
let i = ref 0 in
let lim = ref 0 in
let eof = ref false in
let next () =
- if !i < !lim then begin let c = buf.[!i] in incr i; c end else
+ if !i < !lim then begin let c = Bytes.get buf !i in incr i; c end else
if !eof then raise End_of_file else begin
lim := input ic buf 0 len;
if !lim = 0 then begin eof := true; scan_close_ic ic end else begin
i := 1;
- buf.[0]
+ Bytes.get buf 0
end
end in
create iname next
@@ -402,11 +415,6 @@ end
type ('a, 'b, 'c, 'd) scanner =
('a, Scanning.in_channel, 'b, 'c, 'a -> 'd, 'd) format6 -> 'c
-;;
-
-external string_to_format :
- string -> ('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity"
-;;
(* Reporting errors. *)
exception Scan_failure of string;;
@@ -429,33 +437,6 @@ let bad_end_of_input message =
(Printf.sprintf
"scanning of %s failed: \
premature end of file occurred before end of token" message)
-;;
-
-let int_of_width_opt = function
- | None -> max_int
- | Some width -> width
-;;
-
-let int_of_prec_opt = function
- | None -> max_int
- | Some prec -> prec
-;;
-
-module Sformat = Printf.CamlinternalPr.Sformat;;
-module Tformat = Printf.CamlinternalPr.Tformat;;
-
-let bad_conversion fmt i c =
- invalid_arg
- (Printf.sprintf
- "scanf: bad conversion %%%C, at char number %i \
- in format string \'%s\'" c i (Sformat.to_string fmt))
-;;
-
-let incomplete_format fmt =
- invalid_arg
- (Printf.sprintf "scanf: premature end of format string \'%s\'"
- (Sformat.to_string fmt))
-;;
let bad_float () =
bad_input "no dot or exponent part found in float token"
@@ -467,19 +448,15 @@ let character_mismatch_err c ci =
let character_mismatch c ci =
bad_input (character_mismatch_err c ci)
-;;
-
-let format_mismatch_err fmt1 fmt2 =
- Printf.sprintf
- "format read \'%s\' does not match specification \'%s\'" fmt1 fmt2
-;;
-
-let format_mismatch fmt1 fmt2 = bad_input (format_mismatch_err fmt1 fmt2);;
-(* Checking that 2 format strings are type compatible. *)
-let compatible_format_type fmt1 fmt2 =
- Tformat.summarize_format_type (string_to_format fmt1) =
- Tformat.summarize_format_type (string_to_format fmt2);;
+let rec skip_whites ib =
+ let c = Scanning.peek_char ib in
+ if not (Scanning.eof ib) then begin
+ match c with
+ | ' ' | '\t' | '\n' | '\r' ->
+ Scanning.invalidate_current_char ib; skip_whites ib
+ | _ -> ()
+ end
(* Checking that [c] is indeed in the input, then skips it.
In this case, the character [c] has been explicitly specified in the
@@ -496,28 +473,13 @@ let compatible_format_type fmt1 fmt2 =
We are also careful to treat "\r\n" in the input as an end of line marker:
it always matches a '\n' specification in the input format string. *)
let rec check_char ib c =
- let ci = Scanning.checked_peek_char ib in
- if ci = c then Scanning.invalidate_current_char ib else begin
- match ci with
- | '\r' when c = '\n' ->
- Scanning.invalidate_current_char ib; check_char ib '\n'
- | _ -> character_mismatch c ci
- end
-;;
-
-(* Checks that the current char is indeed one of the stopper characters,
- then skips it.
- Be careful that if ib has no more character this procedure should
- just do nothing (since %s@c defaults to the entire rest of the
- buffer, when no character c can be found in the input). *)
-let ignore_stoppers stps ib =
- if stps <> [] && not (Scanning.eof ib) then
- let ci = Scanning.peek_char ib in
- if List.memq ci stps then Scanning.invalidate_current_char ib else
- let sr = String.concat "" (List.map (String.make 1) stps) in
- bad_input
- (Printf.sprintf "looking for one of range %S, found %C" sr ci)
-;;
+ if c = ' ' then skip_whites ib else
+ let ci = Scanning.checked_peek_char ib in
+ if ci = c then Scanning.invalidate_current_char ib else
+ match ci with
+ | '\r' when c = '\n' ->
+ Scanning.invalidate_current_char ib; check_char ib '\n'
+ | _ -> character_mismatch c ci
(* Extracting tokens from the output token buffer. *)
@@ -701,7 +663,7 @@ let scan_optionally_signed_int width ib =
scan_unsigned_int width ib
;;
-let scan_int_conv conv width _prec ib =
+let scan_int_conv conv width ib =
match conv with
| 'b' -> scan_binary_int width ib
| 'd' -> scan_optionally_signed_decimal_int width ib
@@ -791,7 +753,7 @@ let scan_float width precision ib =
scan_exp_part width ib, precision
;;
-let scan_Float width precision ib =
+let scan_caml_float width precision ib =
let width = scan_optionally_signed_decimal_int width ib in
if width = 0 then bad_float () else
let c = Scanning.peek_char ib in
@@ -805,12 +767,11 @@ let scan_Float width precision ib =
| 'e' | 'E' ->
scan_exp_part width ib
| _ -> bad_float ()
-;;
(* Scan a regular string:
stops when encountering a space, if no scanning indication has been given;
- otherwise, stops when encountering one of the characters in the scanning
- indication list [stp].
+ otherwise, stops when encountering the characters in the scanning
+ indication [stp].
It also stops at end of file or when the maximum number of characters has
been read.*)
let scan_string stp width ib =
@@ -818,12 +779,14 @@ let scan_string stp width ib =
if width = 0 then width else
let c = Scanning.peek_char ib in
if Scanning.eof ib then width else
- if stp = [] then
- match c with
- | ' ' | '\t' | '\n' | '\r' -> width
- | c -> loop (Scanning.store_char width ib c) else
- if List.memq c stp then Scanning.skip_char width ib else
- loop (Scanning.store_char width ib c) in
+ match stp with
+ | Some c' when c = c' -> Scanning.skip_char width ib
+ | Some _ -> loop (Scanning.store_char width ib c)
+ | None ->
+ match c with
+ | ' ' | '\t' | '\n' | '\r' -> width
+ | _ -> loop (Scanning.store_char width ib c)
+ in
loop width
;;
@@ -925,7 +888,7 @@ let scan_backslash_char width ib =
;;
(* Scan a character (an OCaml token). *)
-let scan_Char width ib =
+let scan_caml_char width ib =
let rec find_start width =
match Scanning.checked_peek_char ib with
@@ -948,7 +911,7 @@ let scan_Char width ib =
;;
(* Scan a delimited string (an OCaml token). *)
-let scan_String width ib =
+let scan_caml_string width ib =
let rec find_start width =
match Scanning.checked_peek_char ib with
@@ -981,8 +944,7 @@ let scan_String width ib =
;;
(* Scan a boolean (an OCaml token). *)
-let scan_bool width ib =
- if width < 4 then bad_token_length "a boolean" else
+let scan_bool ib =
let c = Scanning.checked_peek_char ib in
let m =
match c with
@@ -991,560 +953,383 @@ let scan_bool width ib =
| c ->
bad_input
(Printf.sprintf "the character %C cannot start a boolean" c) in
- scan_string [] (min width m) ib
-;;
-
-(* Reading char sets in %[...] conversions. *)
-type char_set =
- | Pos_set of string (* Positive (regular) set. *)
- | Neg_set of string (* Negative (complementary) set. *)
-;;
-
-
-(* Char sets are read as sub-strings in the format string. *)
-let scan_range fmt j =
-
- let len = Sformat.length fmt in
-
- let buffer = Buffer.create len in
-
- let rec scan_closing j =
- if j >= len then incomplete_format fmt else
- match Sformat.get fmt j with
- | ']' -> j, Buffer.contents buffer
- | '%' ->
- let j = j + 1 in
- if j >= len then incomplete_format fmt else
- begin match Sformat.get fmt j with
- | '%' | '@' as c ->
- Buffer.add_char buffer c;
- scan_closing (j + 1)
- | c -> bad_conversion fmt j c
- end
- | c ->
- Buffer.add_char buffer c;
- scan_closing (j + 1) in
-
- let scan_first_pos j =
- if j >= len then incomplete_format fmt else
- match Sformat.get fmt j with
- | ']' as c ->
- Buffer.add_char buffer c;
- scan_closing (j + 1)
- | _ -> scan_closing j in
-
- let scan_first_neg j =
- if j >= len then incomplete_format fmt else
- match Sformat.get fmt j with
- | '^' ->
- let j = j + 1 in
- let k, char_set = scan_first_pos j in
- k, Neg_set char_set
- | _ ->
- let k, char_set = scan_first_pos j in
- k, Pos_set char_set in
-
- scan_first_neg j
-;;
-
-(* Char sets are now represented as bit vectors that are represented as
- byte strings. *)
-
-(* Bit manipulations into bytes. *)
-let set_bit_of_byte byte idx b =
- (b lsl idx) lor (byte land (* mask idx *) (lnot (1 lsl idx)))
-;;
-
-let get_bit_of_byte byte idx = (byte lsr idx) land 1;;
-
-(* Bit manipulations in vectors of bytes represented as strings. *)
-let set_bit_of_range r c b =
- let idx = c land 0x7 in
- let ydx = c lsr 3 in
- let byte = r.[ydx] in
- r.[ydx] <- char_of_int (set_bit_of_byte (int_of_char byte) idx b)
-;;
-
-let get_bit_of_range r c =
- let idx = c land 0x7 in
- let ydx = c lsr 3 in
- let byte = r.[ydx] in
- get_bit_of_byte (int_of_char byte) idx
-;;
-
-(* Char sets represented as bit vectors represented as fixed length byte
- strings. *)
-(* Create a full or empty set of chars. *)
-let make_range bit =
- let c = char_of_int (if bit = 0 then 0 else 0xFF) in
- String.make 32 c
-;;
-
-(* Test if a char belongs to a set of chars. *)
-let get_char_in_range r c = get_bit_of_range r (int_of_char c);;
-
-let bit_not b = (lnot b) land 1;;
-
-(* Build the bit vector corresponding to the set of characters
- that belongs to the string argument [set].
- (In the [Scanf] module [set] is always a sub-string of the format.) *)
-let make_char_bit_vect bit set =
- let r = make_range (bit_not bit) in
- let lim = String.length set - 1 in
- let rec loop bit rp i =
- if i <= lim then
- match set.[i] with
- | '-' when rp ->
- (* if i = 0 then rp is false (since the initial call is
- loop bit false 0). Hence i >= 1 and the following is safe. *)
- let c1 = set.[i - 1] in
- let i = succ i in
- if i > lim then loop bit false (i - 1) else
- let c2 = set.[i] in
- for j = int_of_char c1 to int_of_char c2 do
- set_bit_of_range r j bit done;
- loop bit false (succ i)
- | _ ->
- set_bit_of_range r (int_of_char set.[i]) bit;
- loop bit true (succ i) in
- loop bit false 0;
- r
-;;
-
-(* Compute the predicate on chars corresponding to a char set. *)
-let make_predicate bit set stp =
- let r = make_char_bit_vect bit set in
- List.iter
- (fun c -> set_bit_of_range r (int_of_char c) (bit_not bit)) stp;
- (fun c -> get_char_in_range r c)
-;;
-
-let make_setp stp char_set =
- match char_set with
- | Pos_set set ->
- begin match String.length set with
- | 0 -> (fun _ -> 0)
- | 1 ->
- let p = set.[0] in
- (fun c -> if c == p then 1 else 0)
- | 2 ->
- let p1 = set.[0] and p2 = set.[1] in
- (fun c -> if c == p1 || c == p2 then 1 else 0)
- | 3 ->
- let p1 = set.[0] and p2 = set.[1] and p3 = set.[2] in
- if p2 = '-' then make_predicate 1 set stp else
- (fun c -> if c == p1 || c == p2 || c == p3 then 1 else 0)
- | _ -> make_predicate 1 set stp
- end
- | Neg_set set ->
- begin match String.length set with
- | 0 -> (fun _ -> 1)
- | 1 ->
- let p = set.[0] in
- (fun c -> if c != p then 1 else 0)
- | 2 ->
- let p1 = set.[0] and p2 = set.[1] in
- (fun c -> if c != p1 && c != p2 then 1 else 0)
- | 3 ->
- let p1 = set.[0] and p2 = set.[1] and p3 = set.[2] in
- if p2 = '-' then make_predicate 0 set stp else
- (fun c -> if c != p1 && c != p2 && c != p3 then 1 else 0)
- | _ -> make_predicate 0 set stp
- end
-;;
-
-let setp_table = Hashtbl.create 7;;
-
-let add_setp stp char_set setp =
- let char_set_tbl =
- try Hashtbl.find setp_table char_set with
- | Not_found ->
- let char_set_tbl = Hashtbl.create 3 in
- Hashtbl.add setp_table char_set char_set_tbl;
- char_set_tbl in
- Hashtbl.add char_set_tbl stp setp
-;;
+ scan_string None m ib
-let find_setp stp char_set =
- try Hashtbl.find (Hashtbl.find setp_table char_set) stp with
- | Not_found ->
- let setp = make_setp stp char_set in
- add_setp stp char_set setp;
- setp
-;;
-
-let scan_chars_in_char_set stp char_set width ib =
- let rec loop_pos1 cp1 width =
- if width = 0 then width else
- let c = Scanning.peek_char ib in
- if Scanning.eof ib then width else
- if c == cp1
- then loop_pos1 cp1 (Scanning.store_char width ib c)
- else width
- and loop_pos2 cp1 cp2 width =
- if width = 0 then width else
- let c = Scanning.peek_char ib in
- if Scanning.eof ib then width else
- if c == cp1 || c == cp2
- then loop_pos2 cp1 cp2 (Scanning.store_char width ib c)
- else width
- and loop_pos3 cp1 cp2 cp3 width =
- if width = 0 then width else
- let c = Scanning.peek_char ib in
- if Scanning.eof ib then width else
- if c == cp1 || c == cp2 || c == cp3
- then loop_pos3 cp1 cp2 cp3 (Scanning.store_char width ib c)
- else width
- and loop_neg1 cp1 width =
- if width = 0 then width else
+(* Scan a string containing elements in char_set and terminated by scan_indic
+ if provided. *)
+let scan_chars_in_char_set char_set scan_indic width ib =
+ let rec scan_chars i stp =
let c = Scanning.peek_char ib in
- if Scanning.eof ib then width else
- if c != cp1
- then loop_neg1 cp1 (Scanning.store_char width ib c)
- else width
- and loop_neg2 cp1 cp2 width =
- if width = 0 then width else
- let c = Scanning.peek_char ib in
- if Scanning.eof ib then width else
- if c != cp1 && c != cp2
- then loop_neg2 cp1 cp2 (Scanning.store_char width ib c)
- else width
- and loop_neg3 cp1 cp2 cp3 width =
- if width = 0 then width else
- let c = Scanning.peek_char ib in
- if Scanning.eof ib then width else
- if c != cp1 && c != cp2 && c != cp3
- then loop_neg3 cp1 cp2 cp3 (Scanning.store_char width ib c)
- else width
- and loop setp width =
- if width = 0 then width else
- let c = Scanning.peek_char ib in
- if Scanning.eof ib then width else
- if setp c == 1
- then loop setp (Scanning.store_char width ib c)
- else width in
-
- let width =
- match char_set with
- | Pos_set set ->
- begin match String.length set with
- | 0 -> loop (fun _ -> 0) width
- | 1 -> loop_pos1 set.[0] width
- | 2 -> loop_pos2 set.[0] set.[1] width
- | 3 when set.[1] != '-' -> loop_pos3 set.[0] set.[1] set.[2] width
- | _ -> loop (find_setp stp char_set) width end
- | Neg_set set ->
- begin match String.length set with
- | 0 -> loop (fun _ -> 1) width
- | 1 -> loop_neg1 set.[0] width
- | 2 -> loop_neg2 set.[0] set.[1] width
- | 3 when set.[1] != '-' -> loop_neg3 set.[0] set.[1] set.[2] width
- | _ -> loop (find_setp stp char_set) width end in
- ignore_stoppers stp ib;
- width
-;;
-
-let get_count t ib =
- match t with
- | 'l' -> Scanning.line_count ib
- | 'n' -> Scanning.char_count ib
- | _ -> Scanning.token_count ib
-;;
-
-let rec skip_whites ib =
- let c = Scanning.peek_char ib in
- if not (Scanning.eof ib) then begin
- match c with
- | ' ' | '\t' | '\n' | '\r' ->
- Scanning.invalidate_current_char ib; skip_whites ib
- | _ -> ()
- end
-;;
+ if i > 0 && not (Scanning.eof ib) && is_in_char_set char_set c &&
+ int_of_char c <> stp then
+ let _ = Scanning.store_char max_int ib c in
+ scan_chars (i - 1) stp;
+ in
+ match scan_indic with
+ | None -> scan_chars width (-1);
+ | Some c ->
+ scan_chars width (int_of_char c);
+ if not (Scanning.eof ib) then
+ let ci = Scanning.peek_char ib in
+ if c = ci then Scanning.invalidate_current_char ib
+ else character_mismatch c ci
(* The global error report function for [Scanf]. *)
let scanf_bad_input ib = function
| Scan_failure s | Failure s ->
let i = Scanning.char_count ib in
- bad_input (Printf.sprintf "scanf: bad input at char number %i: \'%s\'" i s)
+ bad_input (Printf.sprintf "scanf: bad input at char number %i: %S" i s)
| x -> raise x
-;;
-let list_iter_i f l =
- let rec loop i = function
- | [] -> ()
- | [x] -> f i x (* Tail calling [f] *)
- | x :: xs -> f i x; loop (succ i) xs in
- loop 0 l
-;;
+(* Get the content of a counter from an input buffer. *)
+let get_counter ib counter = match counter with
+ | Line_counter -> Scanning.line_count ib
+ | Char_counter -> Scanning.char_count ib
+ | Token_counter -> Scanning.token_count ib
-let ascanf sc fmt =
- let ac = Tformat.ac_of_format fmt in
- match ac.Tformat.ac_rdrs with
- | 0 ->
- Obj.magic (fun f -> sc fmt [||] f)
- | 1 ->
- Obj.magic (fun x f -> sc fmt [| Obj.repr x |] f)
- | 2 ->
- Obj.magic (fun x y f -> sc fmt [| Obj.repr x; Obj.repr y; |] f)
- | 3 ->
- Obj.magic
- (fun x y z f -> sc fmt [| Obj.repr x; Obj.repr y; Obj.repr z; |] f)
- | nargs ->
- let rec loop i args =
- if i >= nargs then
- let a = Array.make nargs (Obj.repr 0) in
- list_iter_i (fun i arg -> a.(nargs - i - 1) <- arg) args;
- Obj.magic (fun f -> sc fmt a f)
- else Obj.magic (fun x -> loop (succ i) (x :: args)) in
- loop 0 []
-;;
-
-(* The [scan_format] main scanning function.
- It takes as arguments:
- - an input buffer [ib] from which to read characters,
- - an error handling function [ef],
- - a format [fmt] that specifies what to read in the input,
- - a vector of user's defined readers [rv],
- - and a function [f] to pass the tokens read to.
-
- Then [scan_format] scans the format and the input buffer in parallel to
- find out tokens as specified by the format; when it finds one token, it
- converts it as specified, remembers the converted value as a future
- argument to the function [f], and continues scanning.
-
- If the entire scanning succeeds (i.e. the format string has been
- exhausted and the buffer has provided tokens according to the
- format string), [f] is applied to the tokens read.
-
- If the scanning or some conversion fails, the main scanning function
- aborts and applies the scanning buffer and a string that explains
- the error to the error handling function [ef] (the error continuation). *)
-
-let scan_format ib ef fmt rv f =
-
- let limr = Array.length rv - 1 in
-
- let return v = Obj.magic v () in
- let delay f x () = f x in
- let stack f = delay (return f) in
- let no_stack f _x = f in
-
- let rec scan fmt =
-
- let lim = Sformat.length fmt - 1 in
-
- let rec scan_fmt ir f i =
- if i > lim then ir, f else
- match Sformat.unsafe_get fmt i with
- | '%' -> scan_skip ir f (succ i)
- | ' ' -> skip_whites ib; scan_fmt ir f (succ i)
- | c -> check_char ib c; scan_fmt ir f (succ i)
-
- and scan_skip ir f i =
- if i > lim then ir, f else
- match Sformat.get fmt i with
- | '_' -> scan_limits true ir f (succ i)
- | _ -> scan_limits false ir f i
-
- and scan_limits skip ir f i =
-
- let rec scan_width i =
- if i > lim then incomplete_format fmt else
- match Sformat.get fmt i with
- | '0' .. '9' as conv ->
- let width, i =
- read_int_literal (decimal_value_of_char conv) (succ i) in
- Some width, i
- | _ -> None, i
-
- and scan_precision i =
- begin
- match Sformat.get fmt i with
- | '.' ->
- let precision, i = read_int_literal 0 (succ i) in
- (Some precision, i)
- | _ -> None, i
- end
+(* Compute the width of a padding option (see "%42{" and "%123("). *)
+let width_of_pad_opt pad_opt = match pad_opt with
+ | None -> max_int
+ | Some width -> width
- and read_int_literal accu i =
- if i > lim then accu, i else
- match Sformat.unsafe_get fmt i with
- | '0' .. '9' as c ->
- let accu = 10 * accu + decimal_value_of_char c in
- read_int_literal accu (succ i)
- | _ -> accu, i in
-
- if i > lim then ir, f else
- let width_opt, i = scan_width i in
- let prec_opt, i = scan_precision i in
- scan_conversion skip width_opt prec_opt ir f i
-
- and scan_conversion skip width_opt prec_opt ir f i =
- let stack = if skip then no_stack else stack in
- let width = int_of_width_opt width_opt in
- let prec = int_of_prec_opt prec_opt in
- match Sformat.get fmt i with
- | '%' | '@' as c ->
- check_char ib c;
- scan_fmt ir f (succ i)
- | '!' ->
- if not (Scanning.end_of_input ib)
- then bad_input "end of input not found" else
- scan_fmt ir f (succ i)
- | ',' ->
- scan_fmt ir f (succ i)
- | 's' ->
- let i, stp = scan_indication (succ i) in
- let _x = scan_string stp width ib in
- scan_fmt ir (stack f (token_string ib)) (succ i)
- | 'S' ->
- let _x = scan_String width ib in
- scan_fmt ir (stack f (token_string ib)) (succ i)
- | '[' (* ']' *) ->
- let i, char_set = scan_range fmt (succ i) in
- let i, stp = scan_indication (succ i) in
- let _x = scan_chars_in_char_set stp char_set width ib in
- scan_fmt ir (stack f (token_string ib)) (succ i)
- | ('c' | 'C') when width = 0 ->
- let c = Scanning.checked_peek_char ib in
- scan_fmt ir (stack f c) (succ i)
- | 'c' ->
- let _x = scan_char width ib in
- scan_fmt ir (stack f (token_char ib)) (succ i)
- | 'C' ->
- let _x = scan_Char width ib in
- scan_fmt ir (stack f (token_char ib)) (succ i)
- | 'd' | 'i' | 'o' | 'u' | 'x' | 'X' as conv ->
- let _x = scan_int_conv conv width prec ib in
- scan_fmt ir (stack f (token_int conv ib)) (succ i)
- | 'N' as conv ->
- scan_fmt ir (stack f (get_count conv ib)) (succ i)
- | 'f' | 'e' | 'E' | 'g' | 'G' ->
- let _x = scan_float width prec ib in
- scan_fmt ir (stack f (token_float ib)) (succ i)
- | 'F' ->
- let _x = scan_Float width prec ib in
- scan_fmt ir (stack f (token_float ib)) (succ i)
-(* | 'B' | 'b' when width = Some 0 ->
- let _x = scan_bool width ib in
- scan_fmt ir (stack f (token_int ib)) (succ i) *)
- | 'B' | 'b' ->
- let _x = scan_bool width ib in
- scan_fmt ir (stack f (token_bool ib)) (succ i)
- | 'r' ->
- if ir > limr then assert false else
- let token = Obj.magic rv.(ir) ib in
- scan_fmt (succ ir) (stack f token) (succ i)
- | 'l' | 'n' | 'L' as conv0 ->
- let i = succ i in
- if i > lim then scan_fmt ir (stack f (get_count conv0 ib)) i else begin
- match Sformat.get fmt i with
- (* This is in fact an integer conversion (e.g. %ld, %ni, or %Lo). *)
- | 'd' | 'i' | 'o' | 'u' | 'x' | 'X' as conv1 ->
- let _x = scan_int_conv conv1 width prec ib in
- (* Look back to the character that triggered the integer conversion
- (this character is either 'l', 'n' or 'L') to find the
- conversion to apply to the integer token read. *)
- begin match conv0 with
- | 'l' -> scan_fmt ir (stack f (token_int32 conv1 ib)) (succ i)
- | 'n' -> scan_fmt ir (stack f (token_nativeint conv1 ib)) (succ i)
- | _ -> scan_fmt ir (stack f (token_int64 conv1 ib)) (succ i) end
- (* This is not an integer conversion, but a regular %l, %n or %L. *)
- | _ -> scan_fmt ir (stack f (get_count conv0 ib)) i end
- | '(' | '{' as conv (* ')' '}' *) ->
- let i = succ i in
- (* Find [mf], the static specification for the format to read. *)
- let j =
- Tformat.sub_format
- incomplete_format bad_conversion conv fmt i in
- let mf = Sformat.sub fmt (Sformat.index_of_int i) (j - 2 - i) in
- (* Read [rf], the specified format string in the input buffer,
- and check its correctness w.r.t. [mf]. *)
- let _x = scan_String width ib in
- let rf = token_string ib in
- if not (compatible_format_type rf mf) then format_mismatch rf mf else
- (* Proceed according to the kind of metaformat found:
- - %{ mf %} simply returns [rf] as the token read,
- - %( mf %) returns [rf] as the first token read, then
- returns a second token obtained by scanning the input with
- format string [rf].
- Behaviour for %( mf %) is mandatory for sake of format string
- typechecking specification. To get pure format string
- substitution behaviour, you should use %_( mf %) that skips the
- first (format string) token and hence properly substitutes [mf] by
- [rf] in the format string argument.
+let stopper_of_formatting_lit fmting =
+ if fmting = Escaped_percent then '%', "" else
+ let str = string_of_formatting_lit fmting in
+ let stp = str.[1] in
+ let sub_str = String.sub str 2 (String.length str - 2) in
+ stp, sub_str
+
+(******************************************************************************)
+ (* Readers managment *)
+
+(* A call to take_format_readers on a format is evaluated into functions
+ taking readers as arguments and aggregate them into an heterogeneous list *)
+(* When all readers are taken, finally pass the list of the readers to the
+ continuation k. *)
+let rec take_format_readers : type a c d e f .
+ ((d, e) heter_list -> e) -> (a, Scanning.in_channel, c, d, e, f) fmt ->
+ d =
+fun k fmt -> match fmt with
+ | Reader fmt_rest ->
+ fun reader ->
+ let new_k readers_rest = k (Cons (reader, readers_rest)) in
+ take_format_readers new_k fmt_rest
+ | Char rest -> take_format_readers k rest
+ | Caml_char rest -> take_format_readers k rest
+ | String (_, rest) -> take_format_readers k rest
+ | Caml_string (_, rest) -> take_format_readers k rest
+ | Int (_, _, _, rest) -> take_format_readers k rest
+ | Int32 (_, _, _, rest) -> take_format_readers k rest
+ | Nativeint (_, _, _, rest) -> take_format_readers k rest
+ | Int64 (_, _, _, rest) -> take_format_readers k rest
+ | Float (_, _, _, rest) -> take_format_readers k rest
+ | Bool rest -> take_format_readers k rest
+ | Alpha rest -> take_format_readers k rest
+ | Theta rest -> take_format_readers k rest
+ | Flush rest -> take_format_readers k rest
+ | String_literal (_, rest) -> take_format_readers k rest
+ | Char_literal (_, rest) -> take_format_readers k rest
+
+ | Scan_char_set (_, _, rest) -> take_format_readers k rest
+ | Scan_get_counter (_, rest) -> take_format_readers k rest
+
+ | Formatting_lit (_, rest) -> take_format_readers k rest
+ | Formatting_gen (Open_tag (Format (fmt, _)), rest) -> take_format_readers k (concat_fmt fmt rest)
+ | Formatting_gen (Open_box (Format (fmt, _)), rest) -> take_format_readers k (concat_fmt fmt rest)
+
+ | Format_arg (_, _, rest) -> take_format_readers k rest
+ | Format_subst (_, fmtty, rest) -> take_fmtty_format_readers k (erase_rel (symm fmtty)) rest
+ | Ignored_param (ign, rest) -> take_ignored_format_readers k ign rest
+
+ | End_of_format -> k Nil
+
+(* Take readers associated to an fmtty coming from a Format_subst "%(...%)". *)
+and take_fmtty_format_readers : type x y a c d e f .
+ ((d, e) heter_list -> e) -> (a, Scanning.in_channel, c, d, x, y) fmtty ->
+ (y, Scanning.in_channel, c, x, e, f) fmt -> d =
+fun k fmtty fmt -> match fmtty with
+ | Reader_ty fmt_rest ->
+ fun reader ->
+ let new_k readers_rest = k (Cons (reader, readers_rest)) in
+ take_fmtty_format_readers new_k fmt_rest fmt
+ | Ignored_reader_ty fmt_rest ->
+ fun reader ->
+ let new_k readers_rest = k (Cons (reader, readers_rest)) in
+ take_fmtty_format_readers new_k fmt_rest fmt
+ | Char_ty rest -> take_fmtty_format_readers k rest fmt
+ | String_ty rest -> take_fmtty_format_readers k rest fmt
+ | Int_ty rest -> take_fmtty_format_readers k rest fmt
+ | Int32_ty rest -> take_fmtty_format_readers k rest fmt
+ | Nativeint_ty rest -> take_fmtty_format_readers k rest fmt
+ | Int64_ty rest -> take_fmtty_format_readers k rest fmt
+ | Float_ty rest -> take_fmtty_format_readers k rest fmt
+ | Bool_ty rest -> take_fmtty_format_readers k rest fmt
+ | Alpha_ty rest -> take_fmtty_format_readers k rest fmt
+ | Theta_ty rest -> take_fmtty_format_readers k rest fmt
+ | Format_arg_ty (_, rest) -> take_fmtty_format_readers k rest fmt
+ | End_of_fmtty -> take_format_readers k fmt
+ | Format_subst_ty (ty1, ty2, rest) ->
+ let ty = trans (symm ty1) ty2 in
+ take_fmtty_format_readers k (concat_fmtty ty rest) fmt
+
+(* Take readers associated to an ignored parameter. *)
+and take_ignored_format_readers : type x y a c d e f .
+ ((d, e) heter_list -> e) -> (a, Scanning.in_channel, c, d, x, y) ignored ->
+ (y, Scanning.in_channel, c, x, e, f) fmt -> d =
+fun k ign fmt -> match ign with
+ | Ignored_reader ->
+ fun reader ->
+ let new_k readers_rest = k (Cons (reader, readers_rest)) in
+ take_format_readers new_k fmt
+ | Ignored_char -> take_format_readers k fmt
+ | Ignored_caml_char -> take_format_readers k fmt
+ | Ignored_string _ -> take_format_readers k fmt
+ | Ignored_caml_string _ -> take_format_readers k fmt
+ | Ignored_int (_, _) -> take_format_readers k fmt
+ | Ignored_int32 (_, _) -> take_format_readers k fmt
+ | Ignored_nativeint (_, _) -> take_format_readers k fmt
+ | Ignored_int64 (_, _) -> take_format_readers k fmt
+ | Ignored_float (_, _) -> take_format_readers k fmt
+ | Ignored_bool -> take_format_readers k fmt
+ | Ignored_format_arg _ -> take_format_readers k fmt
+ | Ignored_format_subst (_, fmtty) -> take_fmtty_format_readers k fmtty fmt
+ | Ignored_scan_char_set _ -> take_format_readers k fmt
+ | Ignored_scan_get_counter _ -> take_format_readers k fmt
+
+(******************************************************************************)
+ (* Generic scanning *)
+
+(* Make a generic scanning function. *)
+(* Scan a stream according to a format and readers obtained by
+ take_format_readers, and aggegate scanned values into an
+ heterogeneous list. *)
+(* Return the heterogeneous list of scanned values. *)
+let rec make_scanf : type a c d e f .
+ Scanning.in_channel -> (a, Scanning.in_channel, c, d, e, f) fmt ->
+ (d, _) heter_list -> (a, f) heter_list =
+fun ib fmt readers -> match fmt with
+ | Char rest ->
+ let _ = scan_char 0 ib in
+ let c = token_char ib in
+ Cons (c, make_scanf ib rest readers)
+ | Caml_char rest ->
+ let _ = scan_caml_char 0 ib in
+ let c = token_char ib in
+ Cons (c, make_scanf ib rest readers)
+
+ | String (pad, Formatting_lit (fmting_lit, rest)) ->
+ let stp, str = stopper_of_formatting_lit fmting_lit in
+ let scan width _ ib = scan_string (Some stp) width ib in
+ let str_rest = String_literal (str, rest) in
+ pad_prec_scanf ib str_rest readers pad No_precision scan token_string
+ | String (pad, rest) ->
+ let scan width _ ib = scan_string None width ib in
+ pad_prec_scanf ib rest readers pad No_precision scan token_string
+
+ | Caml_string (pad, rest) ->
+ let scan width _ ib = scan_caml_string width ib in
+ pad_prec_scanf ib rest readers pad No_precision scan token_string
+ | Int (iconv, pad, prec, rest) ->
+ let c = char_of_iconv iconv in
+ let scan width _ ib = scan_int_conv c width ib in
+ pad_prec_scanf ib rest readers pad prec scan (token_int c)
+ | Int32 (iconv, pad, prec, rest) ->
+ let c = char_of_iconv iconv in
+ let scan width _ ib = scan_int_conv c width ib in
+ pad_prec_scanf ib rest readers pad prec scan (token_int32 c)
+ | Nativeint (iconv, pad, prec, rest) ->
+ let c = char_of_iconv iconv in
+ let scan width _ ib = scan_int_conv c width ib in
+ pad_prec_scanf ib rest readers pad prec scan (token_nativeint c)
+ | Int64 (iconv, pad, prec, rest) ->
+ let c = char_of_iconv iconv in
+ let scan width _ ib = scan_int_conv c width ib in
+ pad_prec_scanf ib rest readers pad prec scan (token_int64 c)
+ | Float (Float_F, pad, prec, rest) ->
+ pad_prec_scanf ib rest readers pad prec scan_caml_float token_float
+ | Float ((Float_f | Float_pf | Float_sf | Float_e | Float_pe | Float_se
+ | Float_E | Float_pE | Float_sE | Float_g | Float_pg | Float_sg
+ | Float_G | Float_pG | Float_sG), pad, prec, rest) ->
+ pad_prec_scanf ib rest readers pad prec scan_float token_float
+
+ | Bool rest ->
+ let _ = scan_bool ib in
+ let b = token_bool ib in
+ Cons (b, make_scanf ib rest readers)
+ | Alpha _ ->
+ invalid_arg "scanf: bad conversion \"%a\""
+ | Theta _ ->
+ invalid_arg "scanf: bad conversion \"%t\""
+ | Reader fmt_rest ->
+ let Cons (reader, readers_rest) = readers in
+ let x = reader ib in
+ Cons (x, make_scanf ib fmt_rest readers_rest)
+ | Flush rest ->
+ if Scanning.end_of_input ib then make_scanf ib rest readers
+ else bad_input "end of input not found"
+
+ | String_literal (str, rest) ->
+ String.iter (check_char ib) str;
+ make_scanf ib rest readers
+ | Char_literal (chr, rest) ->
+ check_char ib chr;
+ make_scanf ib rest readers
+
+ | Format_arg (pad_opt, fmtty, rest) ->
+ let _ = scan_caml_string (width_of_pad_opt pad_opt) ib in
+ let s = token_string ib in
+ let fmt =
+ try format_of_string_fmtty s fmtty
+ with Failure msg -> bad_input msg
+ in
+ Cons (fmt, make_scanf ib rest readers)
+ | Format_subst (pad_opt, fmtty, rest) ->
+ let _ = scan_caml_string (width_of_pad_opt pad_opt) ib in
+ let s = token_string ib in
+ let fmt, fmt' =
+ try
+ let Fmt_EBB fmt = fmt_ebb_of_string s in
+ let Fmt_EBB fmt' = fmt_ebb_of_string s in
+ (* TODO: find a way to avoid reparsing twice *)
+
+ (* TODO: these type-checks below *can* fail because of type
+ ambiguity in presence of ignored-readers: "%_r%d" and "%d%_r"
+ are typed in the same way.
+
+ # Scanf.sscanf "\"%_r%d\"3" "%(%d%_r%)" ignore
+ (fun fmt n -> string_of_format fmt, n);;
+ Exception: CamlinternalFormat.Type_mismatch.
+
+ We should properly catch this exception.
*)
- (* For conversion %{%}, just return this format string as the token
- read and go on with the rest of the format string argument. *)
- if conv = '{' (* '}' *) then scan_fmt ir (stack f rf) j else
- (* Or else, return this format string as the first token read;
- then continue scanning using this format string to get
- the following token read;
- finally go on with the rest of the format string argument. *)
- let ir, nf = scan (string_to_format rf) ir (stack f rf) 0 in
- (* Return the format string read and the value just read,
- then go on with the rest of the format. *)
- scan_fmt ir nf j
-
- | c -> bad_conversion fmt i c
-
- and scan_indication j =
- if j > lim then j - 1, [] else
- match Sformat.get fmt j with
- | '@' ->
- let k = j + 1 in
- if k > lim then j - 1, [] else
- begin match Sformat.get fmt k with
- | '%' ->
- let k = k + 1 in
- if k > lim then j - 1, [] else
- begin match Sformat.get fmt k with
- | '%' | '@' as c -> k, [ c ]
- | _c -> j - 1, []
- end
- | c -> k, [ c ]
- end
- | _c -> j - 1, [] in
-
- scan_fmt in
-
-
- Scanning.reset_token ib;
-
- let v =
- try snd (scan fmt 0 (fun () -> f) 0) with
- | (Scan_failure _ | Failure _ | End_of_file) as exc ->
- stack (delay ef ib) exc in
- return v
-;;
-
-let mkscanf ib ef fmt =
- let sc = scan_format ib ef in
- ascanf sc fmt
-;;
-
-let kscanf ib ef fmt = mkscanf ib ef fmt;;
-
-let bscanf ib = kscanf ib scanf_bad_input;;
-
-let fscanf ic = bscanf (Scanning.from_channel ic);;
-
-let sscanf : string -> ('a, 'b, 'c, 'd) scanner
- = fun s -> bscanf (Scanning.from_string s);;
-
-let scanf fmt = bscanf Scanning.stdib fmt;;
-
-let bscanf_format ib fmt f =
- let fmt = Sformat.unsafe_to_string fmt in
- let fmt1 =
- ignore (scan_String max_int ib);
- token_string ib in
- if not (compatible_format_type fmt1 fmt) then
- format_mismatch fmt1 fmt else
- f (string_to_format fmt1)
-;;
+ type_format fmt (erase_rel fmtty),
+ type_format fmt' (erase_rel (symm fmtty))
+ with Failure msg -> bad_input msg
+ in
+ Cons (Format (fmt, s),
+ make_scanf ib (concat_fmt fmt' rest) readers)
+
+ | Scan_char_set (width_opt, char_set, Formatting_lit (fmting_lit, rest)) ->
+ let stp, str = stopper_of_formatting_lit fmting_lit in
+ let width = width_of_pad_opt width_opt in
+ let _ = scan_chars_in_char_set char_set (Some stp) width ib in
+ let s = token_string ib in
+ let str_rest = String_literal (str, rest) in
+ Cons (s, make_scanf ib str_rest readers)
+ | Scan_char_set (width_opt, char_set, rest) ->
+ let width = width_of_pad_opt width_opt in
+ let _ = scan_chars_in_char_set char_set None width ib in
+ let s = token_string ib in
+ Cons (s, make_scanf ib rest readers)
+ | Scan_get_counter (counter, rest) ->
+ let count = get_counter ib counter in
+ Cons (count, make_scanf ib rest readers)
+
+ | Formatting_lit (formatting_lit, rest) ->
+ String.iter (check_char ib) (string_of_formatting_lit formatting_lit);
+ make_scanf ib rest readers
+ | Formatting_gen (Open_tag (Format (fmt', _)), rest) ->
+ check_char ib '@'; check_char ib '{';
+ make_scanf ib (concat_fmt fmt' rest) readers
+ | Formatting_gen (Open_box (Format (fmt', _)), rest) ->
+ check_char ib '@'; check_char ib '[';
+ make_scanf ib (concat_fmt fmt' rest) readers
+
+ | Ignored_param (ign, rest) ->
+ let Param_format_EBB fmt' = param_format_of_ignored_format ign rest in
+ begin match make_scanf ib fmt' readers with
+ | Cons (_, arg_rest) -> arg_rest
+ | Nil -> assert false
+ end
-let sscanf_format s fmt = bscanf_format (Scanning.from_string s) fmt;;
+ | End_of_format ->
+ Nil
+
+(* Case analysis on padding and precision. *)
+(* Reject formats containing "%*" or "%.*". *)
+(* Pass padding and precision to the generic scanner `scan'. *)
+and pad_prec_scanf : type a c d e f x y z t .
+ Scanning.in_channel -> (a, Scanning.in_channel, c, d, e, f) fmt ->
+ (d, _) heter_list -> (x, y) padding -> (y, z -> a) precision ->
+ (int -> int -> Scanning.in_channel -> t) ->
+ (Scanning.in_channel -> z) ->
+ (x, f) heter_list =
+fun ib fmt readers pad prec scan token -> match pad, prec with
+ | No_padding, No_precision ->
+ let _ = scan max_int max_int ib in
+ let x = token ib in
+ Cons (x, make_scanf ib fmt readers)
+ | No_padding, Lit_precision p ->
+ let _ = scan max_int p ib in
+ let x = token ib in
+ Cons (x, make_scanf ib fmt readers)
+ | Lit_padding ((Right | Zeros), w), No_precision ->
+ let _ = scan w max_int ib in
+ let x = token ib in
+ Cons (x, make_scanf ib fmt readers)
+ | Lit_padding ((Right | Zeros), w), Lit_precision p ->
+ let _ = scan w p ib in
+ let x = token ib in
+ Cons (x, make_scanf ib fmt readers)
+ | Lit_padding (Left, _), _ ->
+ invalid_arg "scanf: bad conversion \"%-\""
+ | Lit_padding ((Right | Zeros), _), Arg_precision ->
+ invalid_arg "scanf: bad conversion \"%*\""
+ | Arg_padding _, _ ->
+ invalid_arg "scanf: bad conversion \"%*\""
+ | No_padding, Arg_precision ->
+ invalid_arg "scanf: bad conversion \"%*\""
+
+(******************************************************************************)
+ (* Defining [scanf] and various flavors of [scanf] *)
+
+type 'a kscanf_result = Args of 'a | Exc of exn
+
+let kscanf ib ef (Format (fmt, str)) =
+ let rec apply : type a b . a -> (a, b) heter_list -> b =
+ fun f args -> match args with
+ | Cons (x, r) -> apply (f x) r
+ | Nil -> f
+ in
+ let k readers f =
+ Scanning.reset_token ib;
+ match try Args (make_scanf ib fmt readers) with
+ | (Scan_failure _ | Failure _ | End_of_file) as exc -> Exc exc
+ | Invalid_argument msg ->
+ invalid_arg (msg ^ " in format \"" ^ String.escaped str ^ "\"")
+ with
+ | Args args -> apply f args
+ | Exc exc -> ef ib exc
+ in
+ take_format_readers k fmt
+
+let kbscanf = kscanf
+
+(***)
+
+let ksscanf s ef fmt = kbscanf (Scanning.from_string s) ef fmt
+let kfscanf ic ef fmt = kbscanf (Scanning.from_channel ic) ef fmt
+let bscanf ib fmt = kscanf ib scanf_bad_input fmt
+let fscanf ic fmt = kscanf (Scanning.from_channel ic) scanf_bad_input fmt
+let sscanf s fmt = kscanf (Scanning.from_string s) scanf_bad_input fmt
+let scanf fmt = kscanf Scanning.stdib scanf_bad_input fmt
+
+(***)
+
+let bscanf_format : Scanning.in_channel -> ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
+ (('a, 'b, 'c, 'd, 'e, 'f) format6 -> 'g) -> 'g =
+ fun ib format f ->
+ let _ = scan_caml_string max_int ib in
+ let str = token_string ib in
+ let fmt' =
+ try format_of_string_format str format
+ with Failure msg -> bad_input msg
+ in
+ f fmt'
+
+let sscanf_format : string -> ('a, 'b, 'c, 'd, 'e, 'f) format6 ->
+ (('a, 'b, 'c, 'd, 'e, 'f) format6 -> 'g) -> 'g =
+ fun s format f -> bscanf_format (Scanning.from_string s) format f
let string_to_String s =
let l = String.length s in
@@ -1566,9 +1351,3 @@ let format_from_string s fmt =
let unescaped s =
sscanf ("\"" ^ s ^ "\"") "%S%!" (fun x -> x)
;;
-
-(*
- Local Variables:
- compile-command: "cd ..; make world"
- End:
-*)
diff --git a/stdlib/scanf.mli b/stdlib/scanf.mli
index a1b3d1acbf..297d6f2d5a 100644
--- a/stdlib/scanf.mli
+++ b/stdlib/scanf.mli
@@ -485,6 +485,16 @@ val kscanf :
exception that aborted the scanning process as arguments.
*)
+val ksscanf :
+ string -> (Scanning.in_channel -> exn -> 'd) ->
+ ('a, 'b, 'c, 'd) scanner
+(** Same as {!Scanf.kscanf} but reads from the given string. *)
+
+val kfscanf :
+ Pervasives.in_channel -> (Scanning.in_channel -> exn -> 'd) ->
+ ('a, 'b, 'c, 'd) scanner
+(** Same as {!Scanf.kscanf}, but reads from the given regular input channel. *)
+
(** {6 Reading format strings from input} *)
val bscanf_format :
diff --git a/stdlib/set.mli b/stdlib/set.mli
index 556ee9388e..1b67398eef 100644
--- a/stdlib/set.mli
+++ b/stdlib/set.mli
@@ -19,6 +19,27 @@
The implementation uses balanced binary trees, and is therefore
reasonably efficient: insertion and membership take time
logarithmic in the size of the set, for instance.
+
+ The [Make] functor constructs implementations for any type, given a
+ [compare] function.
+ For instance:
+ {[
+ module IntPairs =
+ struct
+ type t = int * int
+ let compare (x0,y0) (x1,y1) =
+ match Pervasives.compare x0 x1 with
+ 0 -> Pervasives.compare y0 y1
+ | c -> c
+ end
+
+ module PairsSet = Set.Make(IntPairs)
+
+ let m = PairsSet.(empty |> add (2,3) |> add (5,7) |> add (11,13))
+ ]}
+
+ This creates a new module [PairsSet], with a new type [PairsSet.t]
+ of sets of [int * int].
*)
module type OrderedType =
diff --git a/stdlib/stdLabels.ml b/stdlib/stdLabels.ml
index 35b25e0b71..60713ca0cd 100644
--- a/stdlib/stdLabels.ml
+++ b/stdlib/stdLabels.ml
@@ -18,3 +18,5 @@ module Array = ArrayLabels
module List = ListLabels
module String = StringLabels
+
+module Bytes = BytesLabels
diff --git a/stdlib/stdLabels.mli b/stdlib/stdLabels.mli
index 144936f170..c607a9987d 100644
--- a/stdlib/stdLabels.mli
+++ b/stdlib/stdLabels.mli
@@ -14,12 +14,14 @@
(** Standard labeled libraries.
This meta-module provides labelized version of the {!Array},
- {!List} and {!String} modules.
+ {!Bytes}, {!List} and {!String} modules.
They only differ by their labels. Detailed interfaces can be found
- in [arrayLabels.mli], [listLabels.mli] and [stringLabels.mli].
+ in [arrayLabels.mli], [bytesLabels.mli], [listLabels.mli]
+ and [stringLabels.mli].
*)
module Array = ArrayLabels
+module Bytes = BytesLabels
module List = ListLabels
module String = StringLabels
diff --git a/stdlib/stream.ml b/stdlib/stream.ml
index 753bce0056..751c741a85 100644
--- a/stdlib/stream.ml
+++ b/stdlib/stream.ml
@@ -25,7 +25,7 @@ and 'a data =
| Sbuffio of buffio
and 'a gen = { mutable curr : 'a option option; func : int -> 'a option }
and buffio =
- { ic : in_channel; buff : string; mutable len : int; mutable ind : int }
+ { ic : in_channel; buff : bytes; mutable len : int; mutable ind : int }
;;
exception Failure;;
exception Error of string;;
@@ -37,7 +37,7 @@ let set_data (s : 'a t) (d : 'a data) =
;;
let fill_buff b =
- b.len <- input b.ic b.buff 0 (String.length b.buff); b.ind <- 0
+ b.len <- input b.ic b.buff 0 (Bytes.length b.buff); b.ind <- 0
;;
let rec get_data count d = match d with
@@ -64,7 +64,7 @@ let rec get_data count d = match d with
| Sbuffio b ->
if b.ind >= b.len then fill_buff b;
if b.len == 0 then Sempty else
- let r = Obj.magic (String.unsafe_get b.buff b.ind) in
+ let r = Obj.magic (Bytes.unsafe_get b.buff b.ind) in
(* Warning: anyone using g thinks that an item has been read *)
b.ind <- succ b.ind; Scons(r, d)
| Slazy f -> get_data count (Lazy.force f)
@@ -87,7 +87,7 @@ let rec peek s =
| Sbuffio b ->
if b.ind >= b.len then fill_buff b;
if b.len == 0 then begin set_data s Sempty; None end
- else Some (Obj.magic (String.unsafe_get b.buff b.ind))
+ else Some (Obj.magic (Bytes.unsafe_get b.buff b.ind))
;;
let rec junk s =
@@ -159,9 +159,18 @@ let of_string s =
else None)
;;
+let of_bytes s =
+ let count = ref 0 in
+ from (fun _ ->
+ let c = !count in
+ if c < Bytes.length s
+ then (incr count; Some (Bytes.get s c))
+ else None)
+;;
+
let of_channel ic =
{count = 0;
- data = Sbuffio {ic = ic; buff = String.create 4096; len = 0; ind = 0}}
+ data = Sbuffio {ic = ic; buff = Bytes.create 4096; len = 0; ind = 0}}
;;
(* Stream expressions builders *)
diff --git a/stdlib/stream.mli b/stdlib/stream.mli
index aeb0da1e87..85a846102c 100644
--- a/stdlib/stream.mli
+++ b/stdlib/stream.mli
@@ -46,6 +46,9 @@ val of_list : 'a list -> 'a t
val of_string : string -> char t
(** Return the stream of the characters of the string parameter. *)
+val of_bytes : bytes -> char t
+(** Return the stream of the characters of the bytes parameter. *)
+
val of_channel : in_channel -> char t
(** Return the stream of the characters read from the input channel. *)
diff --git a/stdlib/string.ml b/stdlib/string.ml
index fda40b5279..00ff8be9e7 100644
--- a/stdlib/string.ml
+++ b/stdlib/string.ml
@@ -2,72 +2,53 @@
(* *)
(* OCaml *)
(* *)
-(* Xavier Leroy, projet Cristal, INRIA Rocquencourt *)
+(* Damien Doligez, projet Gallium, INRIA Rocquencourt *)
(* *)
-(* Copyright 1996 Institut National de Recherche en Informatique et *)
+(* Copyright 2014 Institut National de Recherche en Informatique et *)
(* en Automatique. All rights reserved. This file is distributed *)
(* under the terms of the GNU Library General Public License, with *)
(* the special exception on linking described in file ../LICENSE. *)
(* *)
(***********************************************************************)
-(* String operations *)
+(* String operations, based on byte sequence operations *)
external length : string -> int = "%string_length"
external get : string -> int -> char = "%string_safe_get"
-external set : string -> int -> char -> unit = "%string_safe_set"
-external create : int -> string = "caml_create_string"
+external set : bytes -> int -> char -> unit = "%string_safe_set"
+external create : int -> bytes = "caml_create_string"
external unsafe_get : string -> int -> char = "%string_unsafe_get"
-external unsafe_set : string -> int -> char -> unit = "%string_unsafe_set"
-external unsafe_blit : string -> int -> string -> int -> int -> unit
+external unsafe_set : bytes -> int -> char -> unit = "%string_unsafe_set"
+external unsafe_blit : string -> int -> bytes -> int -> int -> unit
= "caml_blit_string" "noalloc"
-external unsafe_fill : string -> int -> int -> char -> unit
+external unsafe_fill : bytes -> int -> int -> char -> unit
= "caml_fill_string" "noalloc"
-let make n c =
- let s = create n in
- unsafe_fill s 0 n c;
- s
+module B = Bytes
-let copy s =
- let len = length s in
- let r = create len in
- unsafe_blit s 0 r 0 len;
- r
+let bts = B.unsafe_to_string
+let bos = B.unsafe_of_string
+let make n c =
+ B.make n c |> bts
+let init n f =
+ B.init n f |> bts
+let copy s =
+ B.copy (bos s) |> bts
let sub s ofs len =
- if ofs < 0 || len < 0 || ofs > length s - len
- then invalid_arg "String.sub"
- else begin
- let r = create len in
- unsafe_blit s ofs r 0 len;
- r
- end
-
-let fill s ofs len c =
- if ofs < 0 || len < 0 || ofs > length s - len
- then invalid_arg "String.fill"
- else unsafe_fill s ofs len c
-
+ B.sub (bos s) ofs len |> bts
+let fill =
+ B.fill
let blit s1 ofs1 s2 ofs2 len =
- if len < 0 || ofs1 < 0 || ofs1 > length s1 - len
- || ofs2 < 0 || ofs2 > length s2 - len
- then invalid_arg "String.blit"
- else unsafe_blit s1 ofs1 s2 ofs2 len
-
-let iter f a =
- for i = 0 to length a - 1 do f(unsafe_get a i) done
-
-let iteri f a =
- for i = 0 to length a - 1 do f i (unsafe_get a i) done
+ B.blit (bos s1) ofs1 s2 ofs2 len
let concat sep l =
match l with
- [] -> ""
+ | [] -> ""
| hd :: tl ->
let num = ref 0 and len = ref 0 in
List.iter (fun s -> incr num; len := !len + length s) l;
- let r = create (!len + length sep * (!num - 1)) in
+ let r = B.create (!len + length sep * (!num - 1)) in
unsafe_blit hd 0 r 0 (length hd);
let pos = ref(length hd) in
List.iter
@@ -77,128 +58,68 @@ let concat sep l =
unsafe_blit s 0 r !pos (length s);
pos := !pos + length s)
tl;
- r
+ Bytes.unsafe_to_string r
+
+let iter f s =
+ B.iter f (bos s)
+let iteri f s =
+ B.iteri f (bos s)
+let map f s =
+ B.map f (bos s) |> bts
+let mapi f s =
+ B.mapi f (bos s) |> bts
+
+(* Beware: we cannot use B.trim or B.escape because they always make a
+ copy, but String.mli spells out some cases where we are not allowed
+ to make a copy. *)
external is_printable: char -> bool = "caml_is_printable"
-external char_code: char -> int = "%identity"
-external char_chr: int -> char = "%identity"
let is_space = function
| ' ' | '\012' | '\n' | '\r' | '\t' -> true
| _ -> false
let trim s =
- let len = length s in
- let i = ref 0 in
- while !i < len && is_space (unsafe_get s !i) do
- incr i
- done;
- let j = ref (len - 1) in
- while !j >= !i && is_space (unsafe_get s !j) do
- decr j
- done;
- if !i = 0 && !j = len - 1 then
- s
- else if !j >= !i then
- sub s !i (!j - !i + 1)
- else
- ""
+ if s = "" then s
+ else if is_space (unsafe_get s 0) || is_space (unsafe_get s (length s - 1))
+ then bts (B.trim (bos s))
+ else s
let escaped s =
- let n = ref 0 in
- for i = 0 to length s - 1 do
- n := !n +
- (match unsafe_get s i with
- | '"' | '\\' | '\n' | '\t' | '\r' | '\b' -> 2
- | c -> if is_printable c then 1 else 4)
- done;
- if !n = length s then s else begin
- let s' = create !n in
- n := 0;
- for i = 0 to length s - 1 do
- begin
- match unsafe_get s i with
- | ('"' | '\\') as c ->
- unsafe_set s' !n '\\'; incr n; unsafe_set s' !n c
- | '\n' ->
- unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'n'
- | '\t' ->
- unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 't'
- | '\r' ->
- unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'r'
- | '\b' ->
- unsafe_set s' !n '\\'; incr n; unsafe_set s' !n 'b'
- | c ->
- if is_printable c then
- unsafe_set s' !n c
- else begin
- let a = char_code c in
- unsafe_set s' !n '\\';
- incr n;
- unsafe_set s' !n (char_chr (48 + a / 100));
- incr n;
- unsafe_set s' !n (char_chr (48 + (a / 10) mod 10));
- incr n;
- unsafe_set s' !n (char_chr (48 + a mod 10))
- end
- end;
- incr n
- done;
- s'
- end
-
-let map f s =
- let l = length s in
- if l = 0 then s else begin
- let r = create l in
- for i = 0 to l - 1 do unsafe_set r i (f(unsafe_get s i)) done;
- r
- end
-
-let uppercase s = map Char.uppercase s
-let lowercase s = map Char.lowercase s
-
-let apply1 f s =
- if length s = 0 then s else begin
- let r = copy s in
- unsafe_set r 0 (f(unsafe_get s 0));
- r
- end
-
-let capitalize s = apply1 Char.uppercase s
-let uncapitalize s = apply1 Char.lowercase s
-
-let rec index_rec s lim i c =
- if i >= lim then raise Not_found else
- if unsafe_get s i = c then i else index_rec s lim (i + 1) c;;
-
-let index s c = index_rec s (length s) 0 c;;
-
-let index_from s i c =
- let l = length s in
- if i < 0 || i > l then invalid_arg "String.index_from" else
- index_rec s l i c;;
-
-let rec rindex_rec s i c =
- if i < 0 then raise Not_found else
- if unsafe_get s i = c then i else rindex_rec s (i - 1) c;;
-
-let rindex s c = rindex_rec s (length s - 1) c;;
+ let rec needs_escape i =
+ if i >= length s then false else
+ match unsafe_get s i with
+ | '"' | '\\' | '\n' | '\t' | '\r' | '\b' -> true
+ | c when is_printable c -> needs_escape (i+1)
+ | _ -> true
+ in
+ if needs_escape 0 then
+ bts (B.escaped (bos s))
+ else
+ s
+let index s c =
+ B.index (bos s) c
+let rindex s c =
+ B.rindex (bos s) c
+let index_from s i c=
+ B.index_from (bos s) i c
let rindex_from s i c =
- if i < -1 || i >= length s then invalid_arg "String.rindex_from" else
- rindex_rec s i c;;
-
+ B.rindex_from (bos s) i c
+let contains s c =
+ B.contains (bos s) c
let contains_from s i c =
- let l = length s in
- if i < 0 || i > l then invalid_arg "String.contains_from" else
- try ignore (index_rec s l i c); true with Not_found -> false;;
-
-let contains s c = contains_from s 0 c;;
-
+ B.contains_from (bos s) i c
let rcontains_from s i c =
- if i < 0 || i >= length s then invalid_arg "String.rcontains_from" else
- try ignore (rindex_rec s i c); true with Not_found -> false;;
+ B.rcontains_from (bos s) i c
+let uppercase s =
+ B.uppercase (bos s) |> bts
+let lowercase s =
+ B.lowercase (bos s) |> bts
+let capitalize s =
+ B.capitalize (bos s) |> bts
+let uncapitalize s =
+ B.uncapitalize (bos s) |> bts
type t = string
diff --git a/stdlib/string.mli b/stdlib/string.mli
index 14f2c82dbb..da6d8351af 100644
--- a/stdlib/string.mli
+++ b/stdlib/string.mli
@@ -13,41 +13,36 @@
(** String operations.
- Given a string [s] of length [l], we call character number in [s]
- the index of a character in [s]. Indexes start at [0], and we will
- call a character number valid in [s] if it falls within the range
- [[0...l-1]]. A position is the point between two characters or at
- the beginning or end of the string. We call a position valid
- in [s] if it falls within the range [[0...l]]. Note that character
- number [n] is between positions [n] and [n+1].
+ A string is an immutable data structure that contains a
+ fixed-length sequence of (single-byte) characters. Each character
+ can be accessed in constant time through its index.
+
+ Given a string [s] of length [l], we can access each of the [l]
+ characters of [s] via its index in the sequence. Indexes start at
+ [0], and we will call an index valid in [s] if it falls within the
+ range [[0...l-1]] (inclusive). A position is the point between two
+ characters or at the beginning or end of the string. We call a
+ position valid in [s] if it falls within the range [[0...l]]
+ (inclusive). Note that the character at index [n] is between
+ positions [n] and [n+1].
Two parameters [start] and [len] are said to designate a valid
substring of [s] if [len >= 0] and [start] and [start+len] are
valid positions in [s].
- OCaml strings can be modified in place, for instance via the
- {!String.set} and {!String.blit} functions described below. This
- possibility should be used rarely and with much care, however, since
- both the OCaml compiler and most OCaml libraries share strings as if
- they were immutable, rather than copying them. In particular,
- string literals are shared: a single copy of the string is created
- at program loading time and returned by all evaluations of the
- string literal. Consider for example:
-
- {[
- # let f () = "foo";;
- val f : unit -> string = <fun>
- # (f ()).[0] <- 'b';;
- - : unit = ()
- # f ();;
- - : string = "boo"
- ]}
-
- Likewise, many functions from the standard library can return string
- literals or one of their string arguments. Therefore, the returned strings
- must not be modified directly. If mutation is absolutely necessary,
- it should be performed on a fresh copy of the string, as produced by
- {!String.copy}.
+ 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].
*)
@@ -55,30 +50,45 @@ external length : string -> int = "%string_length"
(** Return the length (number of characters) of the given string. *)
external get : string -> int -> char = "%string_safe_get"
-(** [String.get s n] returns character number [n] in string [s].
+(** [String.get s n] returns the character at index [n] in string [s].
You can also write [s.[n]] instead of [String.get s n].
- Raise [Invalid_argument] if [n] not a valid character number in [s]. *)
+ Raise [Invalid_argument] if [n] not a valid index in [s]. *)
-external set : string -> int -> char -> unit = "%string_safe_set"
-(** [String.set s n c] modifies string [s] in place,
- replacing the character number [n] by [c].
+external set : bytes -> int -> char -> unit = "%string_safe_set"
+ [@@ocaml.deprecated]
+(** [String.set s n c] modifies byte sequence [s] in place,
+ replacing the byte at index [n] with [c].
You can also write [s.[n] <- c] instead of [String.set s n c].
- Raise [Invalid_argument] if [n] is not a valid character number in [s]. *)
+ Raise [Invalid_argument] if [n] is not a valid index in [s].
-external create : int -> string = "caml_create_string"
-(** [String.create n] returns a fresh string of length [n].
- The string initially contains arbitrary characters.
+ @deprecated This is a deprecated alias of {!Bytes.set}.[ ] *)
- Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
+external create : int -> bytes = "caml_create_string" [@@ocaml.deprecated]
+(** [String.create n] returns a fresh byte sequence of length [n].
+ The sequence is uninitialized and contains arbitrary bytes.
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}.
+
+ @deprecated This is a deprecated alias of {!Bytes.create}.[ ] *)
val make : int -> char -> string
(** [String.make n c] returns a fresh string of length [n],
filled with the character [c].
- Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}.*)
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
+
+val init : int -> (int -> char) -> string
+(** [String.init n f] returns a string of length [n], with character
+ [i] initialized to the result of [f i] (called in increasing
+ index order).
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}.
+
+ @since 4.02.0
+*)
val copy : string -> string
(** Return a copy of the given string. *)
@@ -91,23 +101,23 @@ val sub : string -> int -> int -> string
Raise [Invalid_argument] if [start] and [len] do not
designate a valid substring of [s]. *)
-val fill : string -> int -> int -> char -> unit
-(** [String.fill s start len c] modifies string [s] in place,
- replacing [len] characters by [c], starting at [start].
+val fill : bytes -> int -> int -> char -> unit [@@ocaml.deprecated]
+(** [String.fill s start len c] modifies byte sequence [s] in place,
+ replacing [len] bytes with [c], starting at [start].
Raise [Invalid_argument] if [start] and [len] do not
- designate a valid substring of [s]. *)
+ designate a valid range of [s].
-val blit : string -> int -> string -> int -> int -> unit
+ @deprecated This is a deprecated alias of {!Bytes.fill}.[ ] *)
+
+val blit : string -> int -> bytes -> int -> int -> unit
(** [String.blit src srcoff dst dstoff len] copies [len] characters
- from string [src], starting at character number [srcoff], to
- string [dst], starting at character number [dstoff]. It works
- correctly even if [src] and [dst] are the same string,
- and the source and destination intervals overlap.
+ (bytes) from the string [src], starting at index [srcoff], to byte
+ sequence [dst], starting at index [dstoff].
Raise [Invalid_argument] if [srcoff] and [len] do not
designate a valid substring of [src], or if [dstoff] and [len]
- do not designate a valid substring of [dst]. *)
+ do not designate a valid range of [dst]. *)
val concat : string -> string list -> string
(** [String.concat sep sl] concatenates the list of strings [sl],
@@ -122,19 +132,24 @@ val iteri : (int -> char -> unit) -> string -> unit
(** Same as {!String.iter}, but the
function is applied to the index of the element as first argument
(counting from 0), and the character itself as second argument.
- @since 4.00.0
-*)
+ @since 4.00.0 *)
val map : (char -> char) -> string -> string
-(** [String.map f s] applies function [f] in turn to all
- the characters of [s] and stores the results in a new string that
- is returned.
- @since 4.00.0 *)
+(** [String.map f s] applies function [f] in turn to all the
+ characters of [s] (in increasing index order) and stores the
+ results in a new string that is returned.
+ @since 4.00.0 *)
+
+val mapi : (int -> char -> char) -> string -> string
+(** [String.mapi f s] calls [f] with each character of [s] and its
+ index (in increasing index order) and stores the results in a new
+ string that is returned.
+ @since 4.02.0 *)
val trim : string -> string
(** Return a copy of the argument, without leading and trailing
whitespace. The characters regarded as whitespace are: [' '],
- ['\012'], ['\n'], ['\r'], and ['\t']. If there is no leading nor
+ ['\012'], ['\n'], ['\r'], and ['\t']. If there is neither leading nor
trailing whitespace character in the argument, return the original
string itself, not a copy.
@since 4.00.0 *)
@@ -147,19 +162,19 @@ val escaped : string -> string
not a copy. Its inverse function is Scanf.unescaped. *)
val index : string -> char -> int
-(** [String.index s c] returns the character number of the first
+(** [String.index s c] returns the index of the first
occurrence of character [c] in string [s].
Raise [Not_found] if [c] does not occur in [s]. *)
val rindex : string -> char -> int
-(** [String.rindex s c] returns the character number of the last
+(** [String.rindex s c] returns the index of the last
occurrence of character [c] in string [s].
Raise [Not_found] if [c] does not occur in [s]. *)
val index_from : string -> int -> char -> int
-(** [String.index_from s i c] returns the character number of the
+(** [String.index_from s i c] returns the index of the
first occurrence of character [c] in string [s] after position [i].
[String.index s c] is equivalent to [String.index_from s 0 c].
@@ -167,7 +182,7 @@ val index_from : string -> int -> char -> int
Raise [Not_found] if [c] does not occur in [s] after position [i]. *)
val rindex_from : string -> int -> char -> int
-(** [String.rindex_from s i c] returns the character number of the
+(** [String.rindex_from s i c] returns the index of the
last occurrence of character [c] in string [s] before position [i+1].
[String.rindex s c] is equivalent to
[String.rindex_from s (String.length s - 1) c].
@@ -224,8 +239,11 @@ val compare: t -> t -> int
(* The following is for system use only. Do not call directly. *)
external unsafe_get : string -> int -> char = "%string_unsafe_get"
-external unsafe_set : string -> int -> char -> unit = "%string_unsafe_set"
+external unsafe_set : bytes -> int -> char -> unit = "%string_unsafe_set"
+ [@@ocaml.deprecated]
external unsafe_blit :
- string -> int -> string -> int -> int -> unit = "caml_blit_string" "noalloc"
+ string -> int -> bytes -> int -> int -> unit
+ = "caml_blit_string" "noalloc"
external unsafe_fill :
- string -> int -> int -> char -> unit = "caml_fill_string" "noalloc"
+ bytes -> int -> int -> char -> unit = "caml_fill_string" "noalloc"
+ [@@ocaml.deprecated]
diff --git a/stdlib/stringLabels.mli b/stdlib/stringLabels.mli
index 8e2e6d3798..dcef6db036 100644
--- a/stdlib/stringLabels.mli
+++ b/stdlib/stringLabels.mli
@@ -17,61 +17,71 @@ external length : string -> int = "%string_length"
(** Return the length (number of characters) of the given string. *)
external get : string -> int -> char = "%string_safe_get"
-(** [String.get s n] returns character number [n] in string [s].
- The first character is character number 0.
- The last character is character number [String.length s - 1].
+(** [String.get s n] returns the character at index [n] in string [s].
You can also write [s.[n]] instead of [String.get s n].
- Raise [Invalid_argument "index out of bounds"]
- if [n] is outside the range 0 to [(String.length s - 1)]. *)
+ Raise [Invalid_argument] if [n] not a valid index in [s]. *)
-
-external set : string -> int -> char -> unit = "%string_safe_set"
-(** [String.set s n c] modifies string [s] in place,
- replacing the character number [n] by [c].
+external set : bytes -> int -> char -> unit = "%string_safe_set"
+ [@@ocaml.deprecated]
+(** [String.set s n c] modifies byte sequence [s] in place,
+ replacing the byte at index [n] with [c].
You can also write [s.[n] <- c] instead of [String.set s n c].
- Raise [Invalid_argument "index out of bounds"]
- if [n] is outside the range 0 to [(String.length s - 1)]. *)
-external create : int -> string = "caml_create_string"
-(** [String.create n] returns a fresh string of length [n].
- The string initially contains arbitrary characters.
- Raise [Invalid_argument] if [n < 0] or [n > Sys.max_string_length].
-*)
+ Raise [Invalid_argument] if [n] is not a valid index in [s].
+
+ @deprecated This is a deprecated alias of {!Bytes.set}. *)
+
+external create : int -> bytes = "caml_create_string" [@@ocaml.deprecated]
+(** [String.create n] returns a fresh byte sequence of length [n].
+ The sequence is uninitialized and contains arbitrary bytes.
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}.
+
+ @deprecated This is a deprecated alias of {!Bytes.create}. *)
val make : int -> char -> string
(** [String.make n c] returns a fresh string of length [n],
filled with the character [c].
- Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}.*)
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
+
+val init : int -> f:(int -> char) -> string
+(** [init n f] returns a string of length [n],
+ with character [i] initialized to the result of [f i].
+
+ Raise [Invalid_argument] if [n < 0] or [n > ]{!Sys.max_string_length}. *)
val copy : string -> string
(** Return a copy of the given string. *)
val sub : string -> pos:int -> len:int -> string
(** [String.sub s start len] returns a fresh string of length [len],
- containing the characters number [start] to [start + len - 1]
- of string [s].
- Raise [Invalid_argument] if [start] and [len] do not
- designate a valid substring of [s]; that is, if [start < 0],
- or [len < 0], or [start + len > ]{!StringLabels.length}[ s]. *)
+ containing the substring of [s] that starts at position [start] and
+ has length [len].
-val fill : string -> pos:int -> len:int -> char -> unit
-(** [String.fill s start len c] modifies string [s] in place,
- replacing the characters number [start] to [start + len - 1]
- by [c].
Raise [Invalid_argument] if [start] and [len] do not
designate a valid substring of [s]. *)
+val fill : bytes -> pos:int -> len:int -> char -> unit [@@ocaml.deprecated]
+(** [String.fill s start len c] modifies byte sequence [s] in place,
+ replacing [len] bytes by [c], starting at [start].
+
+ Raise [Invalid_argument] if [start] and [len] do not
+ designate a valid substring of [s].
+
+ @deprecated This is a deprecated alias of {!Bytes.fill}. *)
+
val blit :
- src:string -> src_pos:int -> dst:string -> dst_pos:int -> len:int -> unit
-(** [String.blit src srcoff dst dstoff len] copies [len] characters
- from string [src], starting at character number [srcoff], to
- string [dst], starting at character number [dstoff]. It works
- correctly even if [src] and [dst] are the same string,
- and the source and destination chunks overlap.
+ src:string -> src_pos:int -> dst:bytes -> dst_pos:int -> len:int
+ -> unit
+(** [String.blit src srcoff dst dstoff len] copies [len] bytes
+ from the string [src], starting at index [srcoff],
+ to byte sequence [dst], starting at character number [dstoff].
+
Raise [Invalid_argument] if [srcoff] and [len] do not
- designate a valid substring of [src], or if [dstoff] and [len]
- do not designate a valid substring of [dst]. *)
+ designate a valid range of [src], or if [dstoff] and [len]
+ do not designate a valid range of [dst]. *)
val concat : sep:string -> string list -> string
(** [String.concat sep sl] concatenates the list of strings [sl],
@@ -86,8 +96,7 @@ val iteri : f:(int -> char -> unit) -> string -> unit
(** Same as {!String.iter}, but the
function is applied to the index of the element as first argument
(counting from 0), and the character itself as second argument.
- @since 4.00.0
-*)
+ @since 4.00.0 *)
val map : f:(char -> char) -> string -> string
(** [String.map f s] applies function [f] in turn to all
@@ -96,10 +105,11 @@ val map : f:(char -> char) -> string -> string
@since 4.00.0 *)
val trim : string -> string
-(** Return a copy of the argument, without leading and trailing whitespace.
- The characters regarded as whitespace are: [' '], ['\012'], ['\n'],
- ['\r'], and ['\t']. If there is no whitespace character in the argument,
- return the original string itself, not a copy.
+(** Return a copy of the argument, without leading and trailing
+ whitespace. The characters regarded as whitespace are: [' '],
+ ['\012'], ['\n'], ['\r'], and ['\t']. If there is no leading nor
+ trailing whitespace character in the argument, return the original
+ string itself, not a copy.
@since 4.00.0 *)
val escaped : string -> string
@@ -107,28 +117,36 @@ val escaped : string -> string
represented by escape sequences, following the lexical
conventions of OCaml. If there is no special
character in the argument, return the original string itself,
- not a copy. *)
+ not a copy. Its inverse function is Scanf.unescaped. *)
val index : string -> char -> int
-(** [String.index s c] returns the position of the leftmost
+(** [String.index s c] returns the index of the first
occurrence of character [c] in string [s].
+
Raise [Not_found] if [c] does not occur in [s]. *)
val rindex : string -> char -> int
-(** [String.rindex s c] returns the position of the rightmost
+(** [String.rindex s c] returns the index of the last
occurrence of character [c] in string [s].
+
Raise [Not_found] if [c] does not occur in [s]. *)
val index_from : string -> int -> char -> int
-(** Same as {!StringLabels.index}, but start
- searching at the character position given as second argument.
- [String.index s c] is equivalent to [String.index_from s 0 c].*)
+(** [String.index_from s i c] returns the index of the
+ first occurrence of character [c] in string [s] after position [i].
+ [String.index s c] is equivalent to [String.index_from s 0 c].
+
+ Raise [Invalid_argument] if [i] is not a valid position in [s].
+ Raise [Not_found] if [c] does not occur in [s] after position [i]. *)
val rindex_from : string -> int -> char -> int
-(** Same as {!StringLabels.rindex}, but start
- searching at the character position given as second argument.
+(** [String.rindex_from s i c] returns the index of the
+ last occurrence of character [c] in string [s] before position [i+1].
[String.rindex s c] is equivalent to
- [String.rindex_from s (String.length s - 1) c]. *)
+ [String.rindex_from s (String.length s - 1) c].
+
+ Raise [Invalid_argument] if [i+1] is not a valid position in [s].
+ Raise [Not_found] if [c] does not occur in [s] before position [i+1]. *)
val contains : string -> char -> bool
(** [String.contains s c] tests if character [c]
@@ -136,15 +154,18 @@ val contains : string -> char -> bool
val contains_from : string -> int -> char -> bool
(** [String.contains_from s start c] tests if character [c]
- appears in the substring of [s] starting from [start] to the end
- of [s].
- Raise [Invalid_argument] if [start] is not a valid index of [s]. *)
+ appears in [s] after position [start].
+ [String.contains s c] is equivalent to
+ [String.contains_from s 0 c].
+
+ Raise [Invalid_argument] if [start] is not a valid position in [s]. *)
val rcontains_from : string -> int -> char -> bool
(** [String.rcontains_from s stop c] tests if character [c]
- appears in the substring of [s] starting from the beginning
- of [s] to index [stop].
- Raise [Invalid_argument] if [stop] is not a valid index of [s]. *)
+ appears in [s] before position [stop+1].
+
+ Raise [Invalid_argument] if [stop < 0] or [stop+1] is not a valid
+ position in [s]. *)
val uppercase : string -> string
(** Return a copy of the argument, with all lowercase letters
@@ -176,9 +197,11 @@ val compare: t -> t -> int
(* The following is for system use only. Do not call directly. *)
external unsafe_get : string -> int -> char = "%string_unsafe_get"
-external unsafe_set : string -> int -> char -> unit = "%string_unsafe_set"
+external unsafe_set : bytes -> int -> char -> unit = "%string_unsafe_set"
+ [@@ocaml.deprecated]
external unsafe_blit :
- src:string -> src_pos:int -> dst:string -> dst_pos:int -> len:int ->
+ src:string -> src_pos:int -> dst:bytes -> dst_pos:int -> len:int ->
unit = "caml_blit_string" "noalloc"
external unsafe_fill :
- string -> pos:int -> len:int -> char -> unit = "caml_fill_string" "noalloc"
+ bytes -> pos:int -> len:int -> char -> unit = "caml_fill_string" "noalloc"
+ [@@ocaml.deprecated]
diff --git a/stdlib/sys.mli b/stdlib/sys.mli
index 944b1090f6..0f3b131ada 100644
--- a/stdlib/sys.mli
+++ b/stdlib/sys.mli
@@ -99,7 +99,7 @@ val big_endian : bool
@since 4.00.0 *)
val max_string_length : int
-(** Maximum length of a string. *)
+(** Maximum length of strings and byte sequences. *)
val max_array_length : int
(** Maximum length of a normal array. The maximum length of a float
diff --git a/testsuite/external/.ignore b/testsuite/external/.ignore
index 8b57bbb1eb..39e14de915 100644
--- a/testsuite/external/.ignore
+++ b/testsuite/external/.ignore
@@ -26,7 +26,7 @@ camlpdf-0.5
camlp4
camlp4-trunk
camlp5
-camlp5-6.10
+camlp5-git
camlzip
camlzip-1.04
camomile
diff --git a/testsuite/external/Makefile b/testsuite/external/Makefile
index 33acd2ae64..566aaf3921 100644
--- a/testsuite/external/Makefile
+++ b/testsuite/external/Makefile
@@ -44,10 +44,10 @@ all-cygwin: findlib ounit res pcre react ocamltext ocamlssl camlzip cryptokit \
all-macos: findlib res pcre react ocamltext \
ocamlssl camlzip cryptokit sqlite menhir hevea \
- xmllight xmlm omake \
+ xmllight xmlm omake zen \
altergo boomerang vsyml extlib \
ocamlify calendar \
- dbm framac
+ dbm geneweb framac coq compcert
platform:
case `uname -s` in \
@@ -1573,56 +1573,53 @@ distclean::
rm -f ${CSV}.tar.gz
all: csv
-# disabled: need to be updated for new AST stuff
-# # http://pauillac.inria.fr/~ddr/camlp5/
-# CAMLP5=camlp5-6.10
-# ${CAMLP5}.tgz:
-# ${WGET} http://pauillac.inria.fr/~ddr/camlp5/distrib/src/$@
-# camlp5: ${CAMLP5}.tgz
-# printf "%s " "$@" >/dev/tty
-# test -d ${PREFIX}
-# rm -rf ${CAMLP5}
-# tar zxf ${CAMLP5}.tgz
-# ./Patcher.sh ${CAMLP5}
-# ( cd ${CAMLP5} && \
-# export PATH=${PREFIX}/bin:$$PATH && \
-# ./configure --transitional && \
-# ${MAKE} world.opt && \
-# ${MAKE} install )
-# echo ${VERSION} >$@
-# clean::
-# rm -rf ${CAMLP5} camlp5
-# distclean::
-# rm -f ${CAMLP5}.tgz
-# all: camlp5
-
-# disabled: depends on camlp5
-# # http://opensource.geneanet.org/projects/geneweb
-# GENEWEB=gw-6.05-src
-# ${GENEWEB}.tgz:
-# ${WGET} http://opensource.geneanet.org/attachments/download/190/$@
-# geneweb: ${GENEWEB}.tgz camlp5
-# printf "%s " "$@" >/dev/tty
-# test -d ${PREFIX}
-# rm -rf ${GENEWEB}
-# tar zxf ${GENEWEB}.tgz
-# ./Patcher.sh ${GENEWEB}
-# ( cd ${GENEWEB} && \
-# export PATH=${PREFIX}/bin:$$PATH && \
-# sh ./configure && \
-# ${MAKE} )
-# echo ${VERSION} >$@
-# clean::
-# rm -rf ${GENEWEB} geneweb
-# distclean::
-# rm -f ${GENEWEB}.tgz
-# all: geneweb
+# http://pauillac.inria.fr/~ddr/camlp5/
+CAMLP5=camlp5-git
+camlp5:
+ printf "%s " "$@" >/dev/tty
+ test -d ${PREFIX}
+ rm -rf ${CAMLP5}
+ git clone git://scm.gforge.inria.fr/camlp5/camlp5.git ${CAMLP5}
+ ./Patcher.sh ${CAMLP5}
+ ( cd ${CAMLP5} && \
+ export PATH=${PREFIX}/bin:$$PATH && \
+ ./configure --transitional && \
+ ${MAKE} world.opt && \
+ ${MAKE} install )
+ echo ${VERSION} >$@
+clean::
+ rm -rf ${CAMLP5} camlp5
+distclean::
+ rm -f ${CAMLP5}-git
+all: camlp5
+
+disabled: depends on camlp5
+# http://opensource.geneanet.org/projects/geneweb
+GENEWEB=gw-6.05-src
+${GENEWEB}.tgz:
+ ${WGET} http://opensource.geneanet.org/attachments/download/190/$@
+geneweb: ${GENEWEB}.tgz camlp5
+ printf "%s " "$@" >/dev/tty
+ test -d ${PREFIX}
+ rm -rf ${GENEWEB}
+ tar zxf ${GENEWEB}.tgz
+ ./Patcher.sh ${GENEWEB}
+ ( cd ${GENEWEB} && \
+ export PATH=${PREFIX}/bin:$$PATH && \
+ sh ./configure && \
+ ${MAKE} )
+ echo ${VERSION} >$@
+clean::
+ rm -rf ${GENEWEB} geneweb
+distclean::
+ rm -f ${GENEWEB}.tgz
+all: geneweb
# http://coq.inria.fr/download
COQ=coq-8.4pl2
${COQ}.tar.gz:
${WGET} http://coq.inria.fr/distrib/V8.4pl2/files/$@
-xxcoq: ${COQ}.tar.gz camlp5
+coq: ${COQ}.tar.gz camlp5
printf "%s " "$@" >/dev/tty
test -d ${PREFIX}
rm -rf ${COQ}
diff --git a/testsuite/external/camlp5-git.patch b/testsuite/external/camlp5-git.patch
new file mode 100644
index 0000000000..8ea012cc5c
--- /dev/null
+++ b/testsuite/external/camlp5-git.patch
@@ -0,0 +1,12 @@
+diff --git a/Makefile b/Makefile
+index 13622f7..b33a042 100644
+--- camlp5-git/Makefile.orig
++++ camlp5-git/Makefile
+@@ -54,6 +54,7 @@ depend:
+ cd ocaml_stuff; $(MAKE) depend; cd ..
+ for i in $(DIRS) compile; do (cd $$i; $(MAKE) depend; cd ..); done
+
++.PHONY: install
+ install:
+ rm -rf "$(DESTDIR)$(LIBDIR)/$(CAMLP5N)"
+ for i in $(DIRS) compile; do \
diff --git a/testsuite/makefiles/Makefile.common b/testsuite/makefiles/Makefile.common
index ae6aceaa2e..5fdf5a1846 100644
--- a/testsuite/makefiles/Makefile.common
+++ b/testsuite/makefiles/Makefile.common
@@ -110,7 +110,7 @@ defaultclean:
.cmxa.so:
@$(OCAMLOPT) -o $@ -shared -linkall $(ADD_COMPFLAGS) $<
-.mly.ml:
+%.ml %.mli: %.mly
@$(OCAMLYACC) -q $< 2> /dev/null
.mll.ml:
diff --git a/testsuite/tests/asmcomp/lexcmm.mll b/testsuite/tests/asmcomp/lexcmm.mll
index e9efdb60ff..4c262b1122 100644
--- a/testsuite/tests/asmcomp/lexcmm.mll
+++ b/testsuite/tests/asmcomp/lexcmm.mll
@@ -81,7 +81,7 @@ let keyword_table =
(* To buffer string literals *)
-let initial_string_buffer = String.create 256
+let initial_string_buffer = Bytes.create 256
let string_buff = ref initial_string_buffer
let string_index = ref 0
@@ -90,16 +90,16 @@ let reset_string_buffer () =
string_index := 0
let store_string_char c =
- if !string_index >= String.length (!string_buff) then begin
- let new_buff = String.create (String.length (!string_buff) * 2) in
- String.blit (!string_buff) 0 new_buff 0 (String.length (!string_buff));
- string_buff := new_buff
+ 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;
- String.unsafe_set (!string_buff) (!string_index) c;
+ Bytes.unsafe_set (!string_buff) (!string_index) c;
incr string_index
let get_stored_string () =
- let s = String.sub (!string_buff) 0 (!string_index) in
+ let s = Bytes.sub_string (!string_buff) 0 (!string_index) in
string_buff := initial_string_buffer;
s
diff --git a/testsuite/tests/asmcomp/parsecmm.mly b/testsuite/tests/asmcomp/parsecmm.mly
index ad697b6f4b..c81ca619b6 100644
--- a/testsuite/tests/asmcomp/parsecmm.mly
+++ b/testsuite/tests/asmcomp/parsecmm.mly
@@ -172,7 +172,7 @@ componentlist:
;
expr:
INTCONST { Cconst_int $1 }
- | FLOATCONST { Cconst_float $1 }
+ | FLOATCONST { Cconst_float (float_of_string $1) }
| STRING { Cconst_symbol $1 }
| POINTER { Cconst_pointer $1 }
| IDENT { Cvar(find_ident $1) }
@@ -316,7 +316,7 @@ dataitem:
| BYTE INTCONST { Cint8 $2 }
| HALF INTCONST { Cint16 $2 }
| INT INTCONST { Cint(Nativeint.of_int $2) }
- | FLOAT FLOATCONST { Cdouble $2 }
+ | FLOAT FLOATCONST { Cdouble (float_of_string $2) }
| ADDR STRING { Csymbol_address $2 }
| ADDR INTCONST { Clabel_address $2 }
| KSTRING STRING { Cstring $2 }
diff --git a/testsuite/tests/asmcomp/sparc.S b/testsuite/tests/asmcomp/sparc.S
index 53c5fc9029..ea029573a0 100644
--- a/testsuite/tests/asmcomp/sparc.S
+++ b/testsuite/tests/asmcomp/sparc.S
@@ -11,11 +11,11 @@
/***********************************************************************/
#if defined(SYS_solaris) || defined(SYS_elf)
-#define Call_gen_code _call_gen_code
-#define Caml_c_call _caml_c_call
-#else
#define Call_gen_code call_gen_code
#define Caml_c_call caml_c_call
+#else
+#define Call_gen_code _call_gen_code
+#define Caml_c_call _caml_c_call
#endif
.global Call_gen_code
diff --git a/testsuite/tests/backtrace/Makefile b/testsuite/tests/backtrace/Makefile
index 32533fd606..1ca390f942 100644
--- a/testsuite/tests/backtrace/Makefile
+++ b/testsuite/tests/backtrace/Makefile
@@ -14,7 +14,8 @@ BASEDIR=../..
EXECNAME=program$(EXE)
ABCDFILES=backtrace.ml
-OTHERFILES=backtrace2.ml raw_backtrace.ml
+OTHERFILES=backtrace2.ml raw_backtrace.ml \
+ backtrace_deprecated.ml backtrace_slots.ml
default:
$(MAKE) byte
diff --git a/testsuite/tests/backtrace/backtrace_deprecated.ml b/testsuite/tests/backtrace/backtrace_deprecated.ml
new file mode 100644
index 0000000000..7ec5152d0c
--- /dev/null
+++ b/testsuite/tests/backtrace/backtrace_deprecated.ml
@@ -0,0 +1,50 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2008 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. *)
+(* *)
+(***********************************************************************)
+
+(* A test for stack backtraces *)
+
+external get_backtrace : unit -> Printexc.backtrace_slot array option
+ = "caml_get_exception_backtrace"
+
+exception Error of string
+
+let rec f msg n =
+ if n = 0 then raise(Error msg) else 1 + f msg (n-1)
+
+let g msg =
+ try
+ f msg 5
+ with Error "a" -> print_string "a"; print_newline(); 0
+ | Error "b" as exn -> print_string "b"; print_newline(); raise exn
+ | Error "c" -> raise (Error "c")
+
+let run args =
+ try
+ ignore (g args.(0)); print_string "No exception\n"
+ with exn ->
+ Printf.printf "Uncaught exception %s\n" (Printexc.to_string exn);
+ get_backtrace () |> function
+ | None -> ()
+ | Some trace ->
+ Array.iteri
+ (fun i slot -> match Printexc.Slot.format i slot with
+ | None -> ()
+ | Some line -> print_endline line)
+ trace
+
+let _ =
+ Printexc.record_backtrace true;
+ run [| "a" |];
+ run [| "b" |];
+ run [| "c" |];
+ run [| "d" |];
+ run [| |]
diff --git a/testsuite/tests/backtrace/backtrace_deprecated.reference b/testsuite/tests/backtrace/backtrace_deprecated.reference
new file mode 100644
index 0000000000..e9fea9ffe5
--- /dev/null
+++ b/testsuite/tests/backtrace/backtrace_deprecated.reference
@@ -0,0 +1,27 @@
+a
+No exception
+b
+Uncaught exception Backtrace_deprecated.Error("b")
+Raised at file "backtrace_deprecated.ml", line 21, characters 21-32
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 25, characters 4-11
+Re-raised at file "backtrace_deprecated.ml", line 27, characters 68-71
+Called from file "backtrace_deprecated.ml", line 32, characters 11-23
+Uncaught exception Backtrace_deprecated.Error("c")
+Raised at file "backtrace_deprecated.ml", line 28, characters 26-37
+Called from file "backtrace_deprecated.ml", line 32, characters 11-23
+Uncaught exception Backtrace_deprecated.Error("d")
+Raised at file "backtrace_deprecated.ml", line 21, characters 21-32
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 21, characters 42-53
+Called from file "backtrace_deprecated.ml", line 25, characters 4-11
+Called from file "backtrace_deprecated.ml", line 32, characters 11-23
+Uncaught exception Invalid_argument("index out of bounds")
+Raised by primitive operation at file "backtrace_deprecated.ml", line 32, characters 14-22
diff --git a/testsuite/tests/backtrace/backtrace_slots.ml b/testsuite/tests/backtrace/backtrace_slots.ml
new file mode 100644
index 0000000000..8419c61905
--- /dev/null
+++ b/testsuite/tests/backtrace/backtrace_slots.ml
@@ -0,0 +1,72 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, projet Gallium, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2008 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. *)
+(* *)
+(***********************************************************************)
+
+(* A test for stack backtraces *)
+
+let get_backtrace () =
+ let raw_backtrace = Printexc.get_raw_backtrace () in
+ let raw_slots =
+ Array.init (Printexc.raw_backtrace_length raw_backtrace)
+ (Printexc.get_raw_backtrace_slot raw_backtrace) in
+ let convert = Printexc.convert_raw_backtrace_slot in
+ let backtrace = Array.map convert raw_slots in
+ (* we'll play with raw slots a bit to check that hashing and comparison work:
+ - create a hashtable that maps slots to their index in the raw backtrace
+ - create a balanced set of all slots
+ *)
+ let table = Hashtbl.create 100 in
+ 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
+ end) in
+ let slots = Array.fold_right S.add raw_slots S.empty in
+ Array.iteri (fun i slot ->
+ assert (S.mem slot slots);
+ assert (Hashtbl.mem table slot);
+ let j =
+ (* position in the table of the last slot equal to [slot] *)
+ Hashtbl.find table slot in
+ assert (slot = raw_slots.(j));
+ assert (backtrace.(i) = backtrace.(j));
+ ) raw_slots;
+ backtrace
+
+exception Error of string
+
+let rec f msg n =
+ if n = 0 then raise(Error msg) else 1 + f msg (n-1)
+
+let g msg =
+ try
+ f msg 5
+ with Error "a" -> print_string "a"; print_newline(); 0
+ | Error "b" as exn -> print_string "b"; print_newline(); raise exn
+ | Error "c" -> raise (Error "c")
+
+let run args =
+ try
+ ignore (g args.(0)); print_string "No exception\n"
+ with exn ->
+ Printf.printf "Uncaught exception %s\n" (Printexc.to_string exn);
+ get_backtrace () |> Array.iteri
+ (fun i slot -> match Printexc.Slot.format i slot with
+ | None -> ()
+ | Some line -> print_endline line)
+
+let _ =
+ Printexc.record_backtrace true;
+ run [| "a" |];
+ run [| "b" |];
+ run [| "c" |];
+ run [| "d" |];
+ run [| |]
diff --git a/testsuite/tests/backtrace/backtrace_slots.reference b/testsuite/tests/backtrace/backtrace_slots.reference
new file mode 100644
index 0000000000..2336cd5ac3
--- /dev/null
+++ b/testsuite/tests/backtrace/backtrace_slots.reference
@@ -0,0 +1,27 @@
+a
+No exception
+b
+Uncaught exception Backtrace_slots.Error("b")
+Raised at file "backtrace_slots.ml", line 47, characters 21-32
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 51, characters 4-11
+Re-raised at file "backtrace_slots.ml", line 53, characters 68-71
+Called from file "backtrace_slots.ml", line 58, characters 11-23
+Uncaught exception Backtrace_slots.Error("c")
+Raised at file "backtrace_slots.ml", line 54, characters 26-37
+Called from file "backtrace_slots.ml", line 58, characters 11-23
+Uncaught exception Backtrace_slots.Error("d")
+Raised at file "backtrace_slots.ml", line 47, characters 21-32
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 47, characters 42-53
+Called from file "backtrace_slots.ml", line 51, characters 4-11
+Called from file "backtrace_slots.ml", line 58, characters 11-23
+Uncaught exception Invalid_argument("index out of bounds")
+Raised by primitive operation at file "backtrace_slots.ml", line 58, characters 14-22
diff --git a/testsuite/tests/basic-io-2/io.ml b/testsuite/tests/basic-io-2/io.ml
index 14e458cdde..8c71206a83 100644
--- a/testsuite/tests/basic-io-2/io.ml
+++ b/testsuite/tests/basic-io-2/io.ml
@@ -25,7 +25,7 @@ let test msg funct f1 f2 =
let copy_file sz infile ofile =
let ic = open_in_bin infile in
let oc = open_out_bin ofile in
- let buffer = String.create sz in
+ let buffer = Bytes.create sz in
let rec copy () =
let n = input ic buffer 0 sz in
if n = 0 then () else begin
@@ -41,7 +41,7 @@ let copy_file sz infile ofile =
let copy_random sz infile ofile =
let ic = open_in_bin infile in
let oc = open_out_bin ofile in
- let buffer = String.create sz in
+ let buffer = Bytes.create sz in
let rec copy () =
let s = 1 + Random.int sz in
let n = input ic buffer 0 s in
@@ -72,7 +72,7 @@ let copy_seek chunksize infile ofile =
let ic = open_in_bin infile in
let oc = open_out_bin ofile in
let size = in_channel_length ic in
- let buffer = String.create chunksize in
+ let buffer = Bytes.create chunksize in
for i = (size - 1) / chunksize downto 0 do
seek_in ic (i * chunksize);
seek_out oc (i * chunksize);
diff --git a/testsuite/tests/basic-more/pr2719.ml b/testsuite/tests/basic-more/pr2719.ml
new file mode 100644
index 0000000000..f0a9d6a4f9
--- /dev/null
+++ b/testsuite/tests/basic-more/pr2719.ml
@@ -0,0 +1,17 @@
+open Printf
+
+let bug () =
+ let mat = [| [|false|] |]
+ and test = ref false in
+ printf "Value of test at the beginning : %b\n" !test; flush stdout;
+ (try let _ = mat.(0).(-1) in
+ (test := true;
+ printf "Am I going through this block of instructions ?\n";
+ flush stdout)
+ with Invalid_argument _ -> printf "Value of test now : %b\n" !test
+ );
+ (try if mat.(0).(-1) then ()
+ with Invalid_argument _ -> ()
+ )
+
+let () = bug ()
diff --git a/testsuite/tests/basic-more/pr2719.reference b/testsuite/tests/basic-more/pr2719.reference
new file mode 100644
index 0000000000..073d0916d9
--- /dev/null
+++ b/testsuite/tests/basic-more/pr2719.reference
@@ -0,0 +1,4 @@
+Value of test at the beginning : false
+Value of test now : false
+
+All tests succeeded.
diff --git a/testsuite/tests/basic-more/tprintf.ml b/testsuite/tests/basic-more/tprintf.ml
index 9ea9366f5b..5777739fe5 100644
--- a/testsuite/tests/basic-more/tprintf.ml
+++ b/testsuite/tests/basic-more/tprintf.ml
@@ -20,7 +20,8 @@ let test0 () =
sprintf "%.0f" 1.0 = "1" &&
sprintf "%.0f." 1.7 = "2." &&
sprintf "%.1f." 1.0 = "1.0." &&
- sprintf "%0.1f." 12.0 = "12.0." &&
+ (*sprintf "%0.1f." 12.0 = "12.0." &&*)
+ (* >> '0' w/o padding *)
sprintf "%3.1f." 12.0 = "12.0." &&
sprintf "%5.1f." 12.0 = " 12.0." &&
sprintf "%10.1f." 12.0 = " 12.0." &&
@@ -33,7 +34,8 @@ let test0 () =
sprintf "%010.0f." 12.0 = "0000000012." &&
sprintf "% 10.0f." 12.0 = " 12." &&
- sprintf "%0.1f." 12.0 = "12.0." &&
+ (*sprintf "%0.1f." 12.0 = "12.0." &&*)
+ (* >> '0' w/o padding *)
sprintf "%10.1f." 1.001 = " 1.0." &&
sprintf "%05.1f." 1.001 = "001.0."
;;
@@ -59,8 +61,9 @@ test (test2 ());;
(* Testing meta format string printing. *)
let test3 () =
-sprintf "%{toto %s titi.\n%}" "Bonjour %s." = "%s" &&
-sprintf "%{%d%s%}" "kk%dkk%s\n" = "%i%s";;
+ sprintf "%{toto %S titi.\n%}" "Bonjour %S." = "%s" &&
+ sprintf "%{Bonjour %S.%}" "toto %S titi.\n" = "%s"
+;;
test (test3 ());;
(* Testing meta format string arguments. *)
diff --git a/testsuite/tests/basic/constprop.ml b/testsuite/tests/basic/constprop.ml
new file mode 100644
index 0000000000..6661291316
--- /dev/null
+++ b/testsuite/tests/basic/constprop.ml
@@ -0,0 +1,72 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* Test constant propagation through inlining *)
+
+(* constprop.ml is generated from constprop.mlp using
+ cpp constprop.mlp > constprop.ml
+*)
+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" ((x && y, x || y, not x)) ((xh && yh, xh || yh, not xh))
+ 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" ((-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)) ((-xh, xh + yh, xh - yh, xh * yh, xh / yh, xh mod yh, xh land yh, xh lor yh, xh lxor yh, xh lsl sh, xh lsr sh, xh asr sh, xh = yh, xh <> yh, xh < yh, xh <= yh, xh > yh, xh >= yh, succ xh, pred yh))
+ end;
+ begin
+ let x = 3.141592654 and y = 0.341638588598232096 in
+ let xh = hide x and yh = hide y in
+ do_test "floats" ((int_of_float x, x +. y, x -. y, x *. y, x /. y, x = y, x <> y, x < y, x <= y, x > y, x >= y)) ((int_of_float xh, xh +. yh, xh -. yh, xh *. yh, xh /. yh, xh = yh, xh <> yh, xh < yh, xh <= yh, xh > yh, 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" (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)) (Int32.(neg xh, add xh yh, sub xh yh, mul xh yh, div xh yh, rem xh yh, logand xh yh, logor xh yh, logxor xh yh, shift_left xh sh, shift_right xh sh, shift_right_logical xh sh, xh = yh, xh <> yh, xh < yh, xh <= yh, xh > yh, xh >= yh))
+ 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" (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)) (Nativeint.(neg xh, add xh yh, sub xh yh, mul xh yh, div xh yh, rem xh yh, logand xh yh, logor xh yh, logxor xh yh, shift_left xh sh, shift_right xh sh, shift_right_logical xh sh, xh = yh, xh <> yh, xh < yh, xh <= yh, xh > yh, xh >= yh))
+ 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" (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)) (Int64.(neg xh, add xh yh, sub xh yh, mul xh yh, div xh yh, rem xh yh, logand xh yh, logor xh yh, logxor xh yh, shift_left xh sh, shift_right xh sh, shift_right_logical xh sh, xh = yh, xh <> yh, xh < yh, xh <= yh, xh > yh, xh >= yh))
+ end;
+ begin
+ let x = 1000807289 in
+ let xh = hide x in
+ do_test "integer conversions" ((float_of_int x, Int32.of_int x, Nativeint.of_int x, Int64.of_int x)) ((float_of_int xh, Int32.of_int xh, Nativeint.of_int xh, Int64.of_int xh))
+ end;
+ begin
+ let x = 10486393l in
+ let xh = hide x in
+ do_test "32-bit integer conversions" ((Int32.to_int x, Nativeint.of_int32 x, Int64.of_int32 x)) ((Int32.to_int xh, Nativeint.of_int32 xh, Int64.of_int32 xh))
+ end;
+ begin
+ let x = -131134014n in
+ let xh = hide x in
+ do_test "native integer conversions" ((Nativeint.to_int x, Nativeint.to_int32 x, Int64.of_nativeint x)) ((Nativeint.to_int xh, Nativeint.to_int32 xh, Int64.of_nativeint xh))
+ end;
+ begin
+ let x = 531871273453404175L in
+ let xh = hide x in
+ do_test "64-bit integer conversions" ((Int64.to_int x, Int64.to_int32 x, Int64.to_nativeint x)) ((Int64.to_int xh, Int64.to_int32 xh, Int64.to_nativeint xh))
+ end
diff --git a/testsuite/tests/basic/constprop.mlp b/testsuite/tests/basic/constprop.mlp
new file mode 100644
index 0000000000..305a98dd95
--- /dev/null
+++ b/testsuite/tests/basic/constprop.mlp
@@ -0,0 +1,130 @@
+(***********************************************************************)
+(* *)
+(* OCaml *)
+(* *)
+(* Xavier Leroy, 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 Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* 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.reference
new file mode 100644
index 0000000000..59590530ae
--- /dev/null
+++ b/testsuite/tests/basic/constprop.reference
@@ -0,0 +1,10 @@
+booleans: passed
+integers: passed
+floats: passed
+32-bit integers: passed
+native integers: passed
+64-bit integers: passed
+integer conversions: passed
+32-bit integer conversions: passed
+native integer conversions: passed
+64-bit integer conversions: passed
diff --git a/testsuite/tests/basic/tailcalls.ml b/testsuite/tests/basic/tailcalls.ml
index 9a9293aef8..4b33206ee3 100644
--- a/testsuite/tests/basic/tailcalls.ml
+++ b/testsuite/tests/basic/tailcalls.ml
@@ -32,6 +32,15 @@ let indtailcall8 fn a b c d e f g h =
let indtailcall16 fn a b c d e f g h i j k l m n o p =
fn a b c d e f g h i j k l m n o p
+(* regression test for PR#6441: *)
+let rec tailcall16_value_closures a b c d e f g h i j k l m n o p =
+ if a < 0
+ then b
+ else tailcall16_value_closures
+ (a-1) (b+1) (c+2) (d+3) (e+4) (f+5) (g+6) (h+7)
+ (i+8) (j+9) (k+10) (l+11) (m+12) (n+13) (o+14) (p+15)
+and fs = [tailcall16_value_closures]
+
let _ =
print_int (tailcall4 10000000 0 0 0); print_newline();
print_int (tailcall8 10000000 0 0 0 0 0 0 0); print_newline();
@@ -39,4 +48,6 @@ let _ =
print_newline();
print_int (indtailcall8 tailcall8 10 0 0 0 0 0 0 0); print_newline();
print_int (indtailcall16 tailcall16 10 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0);
+ print_newline();
+ print_int (tailcall16_value_closures 10000000 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0);
print_newline()
diff --git a/testsuite/tests/basic/tailcalls.reference b/testsuite/tests/basic/tailcalls.reference
index 0943aba55e..c7117bc954 100644
--- a/testsuite/tests/basic/tailcalls.reference
+++ b/testsuite/tests/basic/tailcalls.reference
@@ -3,3 +3,4 @@
10000001
11
11
+10000001
diff --git a/testsuite/tests/embedded/cmcaml.ml b/testsuite/tests/embedded/cmcaml.ml
index 121cec36fe..b3e9b7e29d 100644
--- a/testsuite/tests/embedded/cmcaml.ml
+++ b/testsuite/tests/embedded/cmcaml.ml
@@ -18,7 +18,7 @@ let rec fib n =
let format_result n =
let r = "Result = " ^ string_of_int n in
(* Allocate gratuitously to test GC *)
- for i = 1 to 1500 do ignore (String.create 256) done;
+ for i = 1 to 1500 do ignore (Bytes.create 256) done;
r
(* Registration *)
diff --git a/testsuite/tests/formats-transition/Makefile b/testsuite/tests/formats-transition/Makefile
new file mode 100644
index 0000000000..9625a3fbc3
--- /dev/null
+++ b/testsuite/tests/formats-transition/Makefile
@@ -0,0 +1,3 @@
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.toplevel
+include $(BASEDIR)/makefiles/Makefile.common
diff --git a/testsuite/tests/formats-transition/deprecated_unsigned_printers.ml b/testsuite/tests/formats-transition/deprecated_unsigned_printers.ml
new file mode 100644
index 0000000000..3127d773af
--- /dev/null
+++ b/testsuite/tests/formats-transition/deprecated_unsigned_printers.ml
@@ -0,0 +1,22 @@
+(* %n, %l, %N and %L have a scanf-specific semantics, but are supposed
+ to be interpreted by Printf and Format as %u, despite this
+ interpretation being mildly deprecated *)
+
+let test format = (Printf.sprintf format (-3) : string)
+;;
+
+let () = Printf.printf "%%n: %B\n"
+ (test "%n" = test "%u")
+;;
+
+let () = Printf.printf "%%l: %B\n"
+ (test "%l" = test "%u")
+;;
+
+let () = Printf.printf "%%N: %B\n"
+ (test "%N" = test "%u")
+;;
+
+let () = Printf.printf "%%L: %B\n"
+ (test "%L" = test "%u")
+;;
diff --git a/testsuite/tests/formats-transition/deprecated_unsigned_printers.ml.reference b/testsuite/tests/formats-transition/deprecated_unsigned_printers.ml.reference
new file mode 100644
index 0000000000..0afeaa2be1
--- /dev/null
+++ b/testsuite/tests/formats-transition/deprecated_unsigned_printers.ml.reference
@@ -0,0 +1,7 @@
+
+# * * val test : (int -> string, unit, string) format -> string = <fun>
+# %n: true
+# %l: true
+# %N: true
+# %L: true
+#
diff --git a/testsuite/tests/formats-transition/ignored_scan_counters.ml b/testsuite/tests/formats-transition/ignored_scan_counters.ml
new file mode 100644
index 0000000000..706a1af6f9
--- /dev/null
+++ b/testsuite/tests/formats-transition/ignored_scan_counters.ml
@@ -0,0 +1,30 @@
+(* Benoît's patch did not support %_[nlNL]; test their behavior *)
+
+(* not supported by Printf or Format: fails at runtime *)
+let () = Printf.printf "%_n"
+;;
+let () = Printf.printf "%_N"
+;;
+let () = Printf.printf "%_l"
+;;
+let () = Printf.printf "%_L"
+;;
+
+let () = Format.printf "%_n"
+;;
+let () = Format.printf "%_N"
+;;
+let () = Format.printf "%_l"
+;;
+let () = Format.printf "%_L"
+;;
+
+(* identity for Scanf *)
+let () = print_endline (Scanf.sscanf "" "%_n" "Hello World!")
+;;
+let () = print_endline (Scanf.sscanf "" "%_N" "Hello World!")
+;;
+let () = print_endline (Scanf.sscanf "" "%_l" "Hello World!")
+;;
+let () = print_endline (Scanf.sscanf "" "%_L" "Hello World!")
+;;
diff --git a/testsuite/tests/formats-transition/ignored_scan_counters.ml.reference b/testsuite/tests/formats-transition/ignored_scan_counters.ml.reference
new file mode 100644
index 0000000000..6d8d098b5a
--- /dev/null
+++ b/testsuite/tests/formats-transition/ignored_scan_counters.ml.reference
@@ -0,0 +1,14 @@
+
+# Exception: Invalid_argument "Printf: bad conversion %_".
+# Exception: Invalid_argument "Printf: bad conversion %_".
+# Exception: Invalid_argument "Printf: bad conversion %_".
+# Exception: Invalid_argument "Printf: bad conversion %_".
+# Exception: Invalid_argument "Printf: bad conversion %_".
+# Exception: Invalid_argument "Printf: bad conversion %_".
+# Exception: Invalid_argument "Printf: bad conversion %_".
+# Exception: Invalid_argument "Printf: bad conversion %_".
+# Hello World!
+# Hello World!
+# Hello World!
+# Hello World!
+#
diff --git a/testsuite/tests/formats-transition/legacy_incompatible_flags.ml b/testsuite/tests/formats-transition/legacy_incompatible_flags.ml
new file mode 100644
index 0000000000..53cf5c26c7
--- /dev/null
+++ b/testsuite/tests/formats-transition/legacy_incompatible_flags.ml
@@ -0,0 +1,20 @@
+(* the legacy parser ignores flags on formatters on which they make no
+ sense *)
+
+let () = Printf.printf "%+s\n" "toto"
+;;
+let () = Printf.printf "%#s\n" "toto"
+;;
+let () = Printf.printf "% s\n" "toto"
+;;
+let () = Printf.printf "%03s\n" "toto"
+;;
+let () = Printf.printf "%03S\n" "toto"
+;;
+let () = Printf.printf "%.3s\n" "toto"
+;;
+
+(* it still fails on flags used with ignored formats (%_d, etc.),
+ but it's unclear how to test that in a backward-compatible way,
+ if we accept that the error message may have changed
+*)
diff --git a/testsuite/tests/formats-transition/legacy_unfinished_modifiers.ml b/testsuite/tests/formats-transition/legacy_unfinished_modifiers.ml
new file mode 100644
index 0000000000..16eca40c17
--- /dev/null
+++ b/testsuite/tests/formats-transition/legacy_unfinished_modifiers.ml
@@ -0,0 +1,18 @@
+(* test whether padding modifiers are accepted without any padding
+ size
+
+ the precision modifier is accepted without precision setting, but it
+ defaults to 0, which is not the same thing as not having precision:
+ %.0f 3.5 => 3
+ %.f 3.5 => 3
+ %f 3.5 => 3.5
+*)
+
+let () = Printf.printf "%0d\n" 3
+;;
+let () = Printf.printf "%-d\n" 3
+;;
+let () = Printf.printf "%.d\n" 3
+;;
+let () = Printf.printf "%.f\n" 3.
+;;
diff --git a/testsuite/tests/formats-transition/legacy_unfinished_modifiers.ml.reference b/testsuite/tests/formats-transition/legacy_unfinished_modifiers.ml.reference
new file mode 100644
index 0000000000..81c05c0dd5
--- /dev/null
+++ b/testsuite/tests/formats-transition/legacy_unfinished_modifiers.ml.reference
@@ -0,0 +1,6 @@
+
+# * * * * * * * * 3
+# 3
+# 3
+# 3
+#
diff --git a/testsuite/tests/gc-roots/globrootsprim.c b/testsuite/tests/gc-roots/globrootsprim.c
index 9a1cc843a1..f7bb32ceab 100644
--- a/testsuite/tests/gc-roots/globrootsprim.c
+++ b/testsuite/tests/gc-roots/globrootsprim.c
@@ -16,10 +16,12 @@
#include "mlvalues.h"
#include "memory.h"
#include "alloc.h"
+#include "gc.h"
-struct block { value v; };
+struct block { value header; value v; };
-#define Block_val(v) ((struct block *) (v))
+#define Block_val(v) ((struct block*) &((value*) v)[-1])
+#define Val_block(b) ((value) &((b)->v))
value gb_get(value vblock)
{
@@ -29,9 +31,10 @@ value gb_get(value vblock)
value gb_classic_register(value v)
{
struct block * b = caml_stat_alloc(sizeof(struct block));
+ b->header = Make_header(1, 0, Caml_black);
b->v = v;
caml_register_global_root(&(b->v));
- return (value) b;
+ return Val_block(b);
}
value gb_classic_set(value vblock, value newval)
@@ -49,9 +52,10 @@ value gb_classic_remove(value vblock)
value gb_generational_register(value v)
{
struct block * b = caml_stat_alloc(sizeof(struct block));
+ b->header = Make_header(1, 0, Caml_black);
b->v = v;
caml_register_generational_global_root(&(b->v));
- return (value) b;
+ return Val_block(b);
}
value gb_generational_set(value vblock, value newval)
diff --git a/testsuite/tests/lib-format/Makefile b/testsuite/tests/lib-format/Makefile
index 0b385ca4bb..7a6297b6f4 100644
--- a/testsuite/tests/lib-format/Makefile
+++ b/testsuite/tests/lib-format/Makefile
@@ -14,5 +14,7 @@ MAIN_MODULE=tformat
ADD_COMPFLAGS=-I $(OTOPDIR)/testsuite/lib
ADD_MODULES=testing
-include ../../makefiles/Makefile.one
-include ../../makefiles/Makefile.common
+BASEDIR=../..
+
+include $(BASEDIR)/makefiles/Makefile.one
+include $(BASEDIR)/makefiles/Makefile.common
diff --git a/testsuite/tests/lib-marshal/intext.ml b/testsuite/tests/lib-marshal/intext.ml
index 06f169e0bb..27ffd64d24 100644
--- a/testsuite/tests/lib-marshal/intext.ml
+++ b/testsuite/tests/lib-marshal/intext.ml
@@ -249,77 +249,77 @@ let marshal_to_buffer s start len v flags =
;;
let test_buffer () =
- let s = String.create 512 in
+ let s = Bytes.create 512 in
marshal_to_buffer s 0 512 1 [];
- test 201 (Marshal.from_string s 0 = 1);
+ test 201 (Marshal.from_bytes s 0 = 1);
marshal_to_buffer s 0 512 (-1) [];
- test 202 (Marshal.from_string s 0 = (-1));
+ test 202 (Marshal.from_bytes s 0 = (-1));
marshal_to_buffer s 0 512 258 [];
- test 203 (Marshal.from_string s 0 = 258);
+ test 203 (Marshal.from_bytes s 0 = 258);
marshal_to_buffer s 0 512 20000 [];
- test 204 (Marshal.from_string s 0 = 20000);
+ test 204 (Marshal.from_bytes s 0 = 20000);
marshal_to_buffer s 0 512 0x12345678 [];
- test 205 (Marshal.from_string s 0 = 0x12345678);
+ test 205 (Marshal.from_bytes s 0 = 0x12345678);
marshal_to_buffer s 0 512 bigint [];
- test 206 (Marshal.from_string s 0 = bigint);
+ test 206 (Marshal.from_bytes s 0 = bigint);
marshal_to_buffer s 0 512 "foobargeebuz" [];
- test 207 (Marshal.from_string s 0 = "foobargeebuz");
+ test 207 (Marshal.from_bytes s 0 = "foobargeebuz");
marshal_to_buffer s 0 512 longstring [];
- test 208 (Marshal.from_string s 0 = longstring);
+ test 208 (Marshal.from_bytes s 0 = longstring);
test 209
(try marshal_to_buffer s 0 512 verylongstring []; false
with Failure "Marshal.to_buffer: buffer overflow" -> true);
marshal_to_buffer s 0 512 3.141592654 [];
- test 210 (Marshal.from_string s 0 = 3.141592654);
+ test 210 (Marshal.from_bytes s 0 = 3.141592654);
marshal_to_buffer s 0 512 () [];
- test 211 (Marshal.from_string s 0 = ());
+ test 211 (Marshal.from_bytes s 0 = ());
marshal_to_buffer s 0 512 A [];
- test 212 (match Marshal.from_string s 0 with
+ test 212 (match Marshal.from_bytes s 0 with
A -> true
| _ -> false);
marshal_to_buffer s 0 512 (B 1) [];
- test 213 (match Marshal.from_string s 0 with
+ test 213 (match Marshal.from_bytes s 0 with
(B 1) -> true
| _ -> false);
marshal_to_buffer s 0 512 (C 2.718) [];
- test 214 (match Marshal.from_string s 0 with
+ test 214 (match Marshal.from_bytes s 0 with
(C f) -> f = 2.718
| _ -> false);
marshal_to_buffer s 0 512 (D "hello, world!") [];
- test 215 (match Marshal.from_string s 0 with
+ test 215 (match Marshal.from_bytes s 0 with
(D "hello, world!") -> true
| _ -> false);
marshal_to_buffer s 0 512 (E 'l') [];
- test 216 (match Marshal.from_string s 0 with
+ test 216 (match Marshal.from_bytes s 0 with
(E 'l') -> true
| _ -> false);
marshal_to_buffer s 0 512 (F(B 1)) [];
- test 217 (match Marshal.from_string s 0 with
+ test 217 (match Marshal.from_bytes s 0 with
(F(B 1)) -> true
| _ -> false);
marshal_to_buffer s 0 512 (G(A, G(B 2, G(C 3.14, G(D "glop", E 'e'))))) [];
- test 218 (match Marshal.from_string s 0 with
+ test 218 (match Marshal.from_bytes s 0 with
(G(A, G(B 2, G(C 3.14, G(D "glop", E 'e'))))) -> true
| _ -> false);
marshal_to_buffer s 0 512 (H(1, A)) [];
- test 219 (match Marshal.from_string s 0 with
+ test 219 (match Marshal.from_bytes s 0 with
(H(1, A)) -> true
| _ -> false);
marshal_to_buffer s 0 512 (I(B 2, 1e-6)) [];
- test 220 (match Marshal.from_string s 0 with
+ test 220 (match Marshal.from_bytes s 0 with
(I(B 2, 1e-6)) -> true
| _ -> false);
let x = D "sharing" in
let y = G(x, x) in
let z = G(y, G(x, y)) in
marshal_to_buffer s 0 512 z [];
- test 221 (match Marshal.from_string s 0 with
+ test 221 (match Marshal.from_bytes s 0 with
G((G((D "sharing" as t1), t2) as t3), G(t4, t5)) ->
t1 == t2 && t3 == t5 && t4 == t1
| _ -> false);
marshal_to_buffer s 0 512 [|1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16|] [];
test 222
- (Marshal.from_string s 0 = [|1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16|]);
+ (Marshal.from_bytes s 0 = [|1;2;3;4;5;6;7;8;9;10;11;12;13;14;15;16|]);
let rec big n = if n <= 0 then A else H(n, big(n-1)) in
test 223
(try marshal_to_buffer s 0 512 (big 1000) []; false
diff --git a/testsuite/tests/lib-printf/Makefile b/testsuite/tests/lib-printf/Makefile
index a8a2947182..dc31633e11 100644
--- a/testsuite/tests/lib-printf/Makefile
+++ b/testsuite/tests/lib-printf/Makefile
@@ -15,5 +15,6 @@ MAIN_MODULE=tprintf
ADD_COMPFLAGS=-I $(OTOPDIR)/testsuite/lib
ADD_MODULES=testing
-include ../../makefiles/Makefile.one
-include ../../makefiles/Makefile.common
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.one
+include $(BASEDIR)/makefiles/Makefile.common
diff --git a/testsuite/tests/lib-printf/tprintf.ml b/testsuite/tests/lib-printf/tprintf.ml
index 47313b325a..2922f8e325 100644
--- a/testsuite/tests/lib-printf/tprintf.ml
+++ b/testsuite/tests/lib-printf/tprintf.ml
@@ -27,10 +27,12 @@ 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");
+ (*test (sprintf "%#d/%#i" 42 43 = "42/43");*)
+ (* >> '#' is incompatible with 'd' *)
test (sprintf "%4d/%5i" 42 43 = " 42/ 43");
test (sprintf "%*d/%*i" 4 42 5 43 = " 42/ 43");
- test (sprintf "%-0+#4d/%-0 #5i" 42 43 = "+42 / 43 ");
+ (*test (sprintf "%-0+#4d/%-0 #5i" 42 43 = "+42 / 43 ");*)
+ (* >> '#' is incompatible with 'd' *)
printf "\nd/i negative\n%!";
test (sprintf "%d/%i" (-42) (-43) = "-42/-43");
@@ -38,21 +40,27 @@ 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");
+ (*test (sprintf "%#d/%#i" (-42) (-43) = "-42/-43");*)
+ (* >> '#' is incompatible with 'd' *)
test (sprintf "%4d/%5i" (-42) (-43) = " -42/ -43");
test (sprintf "%*d/%*i" 4 (-42) 5 (-43) = " -42/ -43");
- test (sprintf "%-0+ #4d/%-0+ #5i" (-42) (-43) = "-42 /-43 ");
+ (*test (sprintf "%-0+ #4d/%-0+ #5i" (-42) (-43) = "-42 /-43 ");*)
+ (* >> '0' is incompatible with '-', '#' is incompatible with 'd' *)
printf "\nu positive\n%!";
test (sprintf "%u" 42 = "42");
test (sprintf "%-4u" 42 = "42 ");
test (sprintf "%04u" 42 = "0042");
- test (sprintf "%+u" 42 = "42");
- test (sprintf "% u" 42 = "42");
- test (sprintf "%#u" 42 = "42");
+ (*test (sprintf "%+u" 42 = "42");*)
+ (* >> '+' is incompatible with 'u' *)
+ (*test (sprintf "% u" 42 = "42");*)
+ (* >> ' ' is incompatible with 'u' *)
+ (*test (sprintf "%#u" 42 = "42");*)
+ (* >> '#' is incompatible with 'u' *)
test (sprintf "%4u" 42 = " 42");
test (sprintf "%*u" 4 42 = " 42");
- test (sprintf "%-0+ #6d" 42 = "+42 ");
+ (*test (sprintf "%-0+ #6d" 42 = "+42 ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 'd' *)
printf "\nu negative\n%!";
begin match Sys.word_size with
@@ -67,12 +75,15 @@ try
test (sprintf "%x" 42 = "2a");
test (sprintf "%-4x" 42 = "2a ");
test (sprintf "%04x" 42 = "002a");
- test (sprintf "%+x" 42 = "2a");
- test (sprintf "% x" 42 = "2a");
+ (*test (sprintf "%+x" 42 = "2a");*)
+ (* >> '+' is incompatible with 'x' *)
+ (*test (sprintf "% x" 42 = "2a");*)
+ (* >> ' ' is incompatible with 'x' *)
test (sprintf "%#x" 42 = "0x2a");
test (sprintf "%4x" 42 = " 2a");
test (sprintf "%*x" 5 42 = " 2a");
- test (sprintf "%-0+ #*x" 5 42 = "0x2a ");
+ (*test (sprintf "%-0+ #*x" 5 42 = "0x2a ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nx negative\n%!";
begin match Sys.word_size with
@@ -87,12 +98,15 @@ try
test (sprintf "%X" 42 = "2A");
test (sprintf "%-4X" 42 = "2A ");
test (sprintf "%04X" 42 = "002A");
- test (sprintf "%+X" 42 = "2A");
- test (sprintf "% X" 42 = "2A");
+ (*test (sprintf "%+X" 42 = "2A");*)
+ (* >> '+' is incompatible with 'X' *)
+ (*test (sprintf "% X" 42 = "2A");*)
+ (* >> ' ' is incompatible with 'X' *)
test (sprintf "%#X" 42 = "0X2A");
test (sprintf "%4X" 42 = " 2A");
test (sprintf "%*X" 5 42 = " 2A");
- test (sprintf "%-0+ #*X" 5 42 = "0X2A ");
+ (*test (sprintf "%-0+ #*X" 5 42 = "0X2A ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nx negative\n%!";
begin match Sys.word_size with
@@ -107,12 +121,15 @@ try
test (sprintf "%o" 42 = "52");
test (sprintf "%-4o" 42 = "52 ");
test (sprintf "%04o" 42 = "0052");
- test (sprintf "%+o" 42 = "52");
- test (sprintf "% o" 42 = "52");
+ (*test (sprintf "%+o" 42 = "52");*)
+ (* >> '+' is incompatible with 'o' *)
+ (*test (sprintf "% o" 42 = "52");*)
+ (* >> '+' is incompatible with 'o' *)
test (sprintf "%#o" 42 = "052");
test (sprintf "%4o" 42 = " 52");
test (sprintf "%*o" 5 42 = " 52");
- test (sprintf "%-0+ #*o" 5 42 = "052 ");
+ (*test (sprintf "%-0+ #*o" 5 42 = "052 ");*)
+ (* >> '-' is incompatible with 'o' *)
printf "\no negative\n%!";
begin match Sys.word_size with
@@ -126,15 +143,20 @@ try
printf "\ns\n%!";
test (sprintf "%s" "foo" = "foo");
test (sprintf "%-5s" "foo" = "foo ");
- test (sprintf "%05s" "foo" = " foo");
- test (sprintf "%+s" "foo" = "foo");
- test (sprintf "% s" "foo" = "foo");
- test (sprintf "%#s" "foo" = "foo");
+ (*test (sprintf "%05s" "foo" = " foo");*)
+ (* >> '0' is incompatible with 's' *)
+ (*test (sprintf "%+s" "foo" = "foo");*)
+ (* >> '+' is incompatible with 's' *)
+ (*test (sprintf "% s" "foo" = "foo");*)
+ (* >> ' ' is incompatible with 's' *)
+ (*test (sprintf "%#s" "foo" = "foo");*)
+ (* >> '#' is incompatible with 's' *)
test (sprintf "%5s" "foo" = " foo");
test (sprintf "%1s" "foo" = "foo");
test (sprintf "%*s" 6 "foo" = " foo");
test (sprintf "%*s" 2 "foo" = "foo");
- test (sprintf "%-0+ #5s" "foo" = "foo ");
+ (*test (sprintf "%-0+ #5s" "foo" = "foo ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 's' *)
test (sprintf "%s@" "foo" = "foo@");
test (sprintf "%s@inria.fr" "foo" = "foo@inria.fr");
test (sprintf "%s@%s" "foo" "inria.fr" = "foo@inria.fr");
@@ -143,9 +165,12 @@ try
test (sprintf "%S" "fo\"o" = "\"fo\\\"o\"");
(* test (sprintf "%-5S" "foo" = "\"foo\" "); padding not done *)
(* test (sprintf "%05S" "foo" = " \"foo\""); padding not done *)
- test (sprintf "%+S" "foo" = "\"foo\"");
- test (sprintf "% S" "foo" = "\"foo\"");
- test (sprintf "%#S" "foo" = "\"foo\"");
+ (*test (sprintf "%+S" "foo" = "\"foo\"");*)
+ (* >> '#' is incompatible with 'S' *)
+ (*test (sprintf "% S" "foo" = "\"foo\"");*)
+ (* >> '#' is incompatible with 'S' *)
+ (*test (sprintf "%#S" "foo" = "\"foo\"");*)
+ (* >> '#' is incompatible with 'S' *)
(* test (sprintf "%5S" "foo" = " \"foo\""); padding not done *)
test (sprintf "%1S" "foo" = "\"foo\"");
(* test (sprintf "%*S" 6 "foo" = " \"foo\""); padding not done *)
@@ -159,9 +184,12 @@ try
test (sprintf "%c" 'c' = "c");
(* test (sprintf "%-4c" 'c' = "c "); padding not done *)
(* test (sprintf "%04c" 'c' = " c"); padding not done *)
- test (sprintf "%+c" 'c' = "c");
- test (sprintf "% c" 'c' = "c");
- test (sprintf "%#c" 'c' = "c");
+ (*test (sprintf "%+c" 'c' = "c");*)
+ (* >> '#' is incompatible with 'c' *)
+ (*test (sprintf "% c" 'c' = "c");*)
+ (* >> '#' is incompatible with 'c' *)
+ (*test (sprintf "%#c" 'c' = "c");*)
+ (* >> '#' is incompatible with 'c' *)
(* test (sprintf "%4c" 'c' = " c"); padding not done *)
(* test (sprintf "%*c" 2 'c' = " c"); padding not done *)
(* test (sprintf "%-0+ #4c" 'c' = "c "); padding not done *)
@@ -171,12 +199,15 @@ try
test (sprintf "%C" '\'' = "'\\''");
(* test (sprintf "%-4C" 'c' = "c "); padding not done *)
(* test (sprintf "%04C" 'c' = " c"); padding not done *)
- test (sprintf "%+C" 'c' = "'c'");
- test (sprintf "% C" 'c' = "'c'");
- test (sprintf "%#C" 'c' = "'c'");
-(* test (sprintf "%4C" 'c' = " 'c'"); padding not done *)
-(* test (sprintf "%*C" 2 'c' = "'c'"); padding not done *)
-(* test (sprintf "%-0+ #4C" 'c' = "'c' "); padding not done *)
+ (*test (sprintf "%+C" 'c' = "'c'");*)
+ (* >> '+' is incompatible with 'C' *)
+ (*test (sprintf "% C" 'c' = "'c'");*)
+ (* >> ' ' is incompatible with 'C' *)
+ (*test (sprintf "%#C" 'c' = "'c'");*)
+ (* >> '#' is incompatible with 'C' *)
+(* test (sprintf "%4C" 'c' = " c"); padding not done *)
+(* test (sprintf "%*C" 2 'c' = " c"); padding not done *)
+(* test (sprintf "%-0+ #4C" 'c' = "c "); padding not done *)
printf "\nf\n%!";
test (sprintf "%f" (-42.42) = "-42.420000");
@@ -184,19 +215,23 @@ try
test (sprintf "%013f" (-42.42) = "-00042.420000");
test (sprintf "%+f" 42.42 = "+42.420000");
test (sprintf "% f" 42.42 = " 42.420000");
- test (sprintf "%#f" 42.42 = "42.420000");
+ (*test (sprintf "%#f" 42.42 = "42.420000");*)
+ (* >> '#' is incompatible with 'f' *)
test (sprintf "%13f" 42.42 = " 42.420000");
test (sprintf "%*f" 12 42.42 = " 42.420000");
- test (sprintf "%-0+ #12f" 42.42 = "+42.420000 ");
+ (*test (sprintf "%-0+ #12f" 42.42 = "+42.420000 ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 'f' *)
test (sprintf "%.3f" (-42.42) = "-42.420");
test (sprintf "%-13.3f" (-42.42) = "-42.420 ");
test (sprintf "%013.3f" (-42.42) = "-00000042.420");
test (sprintf "%+.3f" 42.42 = "+42.420");
test (sprintf "% .3f" 42.42 = " 42.420");
- test (sprintf "%#.3f" 42.42 = "42.420");
+ (*test (sprintf "%#.3f" 42.42 = "42.420");*)
+ (* >> '#' is incompatible with 'f' *)
test (sprintf "%13.3f" 42.42 = " 42.420");
test (sprintf "%*.*f" 12 3 42.42 = " 42.420");
- test (sprintf "%-0+ #12.3f" 42.42 = "+42.420 ");
+ (*test (sprintf "%-0+ #12.3f" 42.42 = "+42.420 ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 'f' *)
(* Under Windows (mingw and maybe also MSVC), the stdlib uses three
digits for the exponent instead of the two used by Linux and BSD.
@@ -240,19 +275,23 @@ try
test (sprintf "%015e" (-42.42) =* "-004.242000e+01");
test (sprintf "%+e" 42.42 =* "+4.242000e+01");
test (sprintf "% e" 42.42 =* " 4.242000e+01");
- test (sprintf "%#e" 42.42 =* "4.242000e+01");
+ (*test (sprintf "%#e" 42.42 =* "4.242000e+01");*)
+ (* >> '#' is incompatible with 'e' *)
test (sprintf "%15e" 42.42 =* " 4.242000e+01");
test (sprintf "%*e" 14 42.42 =* " 4.242000e+01");
- test (sprintf "%-0+ #14e" 42.42 =* "+4.242000e+01 ");
+ (*test (sprintf "%-0+ #14e" 42.42 =* "+4.242000e+01 ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 'e' *)
test (sprintf "%.3e" (-42.42) =* "-4.242e+01");
test (sprintf "%-15.3e" (-42.42) =* "-4.242e+01 ");
test (sprintf "%015.3e" (-42.42) =* "-000004.242e+01");
test (sprintf "%+.3e" 42.42 =* "+4.242e+01");
test (sprintf "% .3e" 42.42 =* " 4.242e+01");
- test (sprintf "%#.3e" 42.42 =* "4.242e+01");
+ (*test (sprintf "%#.3e" 42.42 =* "4.242e+01");*)
+ (* >> '#' is incompatible with 'e' *)
test (sprintf "%15.3e" 42.42 =* " 4.242e+01");
test (sprintf "%*.*e" 11 3 42.42 =* " 4.242e+01");
- test (sprintf "%-0+ #14.3e" 42.42 =* "+4.242e+01 ");
+ (*test (sprintf "%-0+ #14.3e" 42.42 =* "+4.242e+01 ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 'e' *)
printf "\nE\n%!";
test (sprintf "%E" (-42.42) =* "-4.242000E+01");
@@ -260,19 +299,23 @@ try
test (sprintf "%015E" (-42.42) =* "-004.242000E+01");
test (sprintf "%+E" 42.42 =* "+4.242000E+01");
test (sprintf "% E" 42.42 =* " 4.242000E+01");
- test (sprintf "%#E" 42.42 =* "4.242000E+01");
+ (*test (sprintf "%#E" 42.42 =* "4.242000E+01");*)
+ (* >> '#' is incompatible with 'E' *)
test (sprintf "%15E" 42.42 =* " 4.242000E+01");
test (sprintf "%*E" 14 42.42 =* " 4.242000E+01");
- test (sprintf "%-0+ #14E" 42.42 =* "+4.242000E+01 ");
+ (*test (sprintf "%-0+ #14E" 42.42 =* "+4.242000E+01 ");*)
+ (* >> '#' is incompatible with 'E' *)
test (sprintf "%.3E" (-42.42) =* "-4.242E+01");
test (sprintf "%-15.3E" (-42.42) =* "-4.242E+01 ");
test (sprintf "%015.3E" (-42.42) =* "-000004.242E+01");
test (sprintf "%+.3E" 42.42 =* "+4.242E+01");
test (sprintf "% .3E" 42.42 =* " 4.242E+01");
- test (sprintf "%#.3E" 42.42 =* "4.242E+01");
+ (*test (sprintf "%#.3E" 42.42 =* "4.242E+01");*)
+ (* >> '#' is incompatible with 'E' *)
test (sprintf "%15.3E" 42.42 =* " 4.242E+01");
test (sprintf "%*.*E" 11 3 42.42 =* " 4.242E+01");
- test (sprintf "%-0+ #14.3E" 42.42 =* "+4.242E+01 ");
+ (*test (sprintf "%-0+ #14.3E" 42.42 =* "+4.242E+01 ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 'E' *)
(* %g gives strange results that correspond to neither %f nor %e
printf "\ng\n%!";
@@ -302,10 +345,12 @@ try
test (sprintf "%04ld/%05li" 42l 43l = "0042/00043");
test (sprintf "%+ld/%+li" 42l 43l = "+42/+43");
test (sprintf "% ld/% li" 42l 43l = " 42/ 43");
- test (sprintf "%#ld/%#li" 42l 43l = "42/43");
+ (*test (sprintf "%#ld/%#li" 42l 43l = "42/43");*)
+ (* >> '#' is incompatible with 'ld' *)
test (sprintf "%4ld/%5li" 42l 43l = " 42/ 43");
test (sprintf "%*ld/%*li" 4 42l 5 43l = " 42/ 43");
- test (sprintf "%-0+#4ld/%-0 #5li" 42l 43l = "+42 / 43 ");
+ (*test (sprintf "%-0+#4ld/%-0 #5li" 42l 43l = "+42 / 43 ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 'ld' *)
printf "\nld/li negative\n%!";
test (sprintf "%ld/%li" (-42l) (-43l) = "-42/-43");
@@ -313,21 +358,27 @@ try
test (sprintf "%04ld/%05li" (-42l) (-43l) = "-042/-0043");
test (sprintf "%+ld/%+li" (-42l) (-43l) = "-42/-43");
test (sprintf "% ld/% li" (-42l) (-43l) = "-42/-43");
- test (sprintf "%#ld/%#li" (-42l) (-43l) = "-42/-43");
+ (*test (sprintf "%#ld/%#li" (-42l) (-43l) = "-42/-43");*)
+ (* >> '#' is incompatible with 'ld' *)
test (sprintf "%4ld/%5li" (-42l) (-43l) = " -42/ -43");
test (sprintf "%*ld/%*li" 4 (-42l) 5 (-43l) = " -42/ -43");
- test (sprintf "%-0+ #4ld/%-0+ #5li" (-42l) (-43l) = "-42 /-43 ");
+ (*test (sprintf "%-0+ #4ld/%-0+ #5li" (-42l) (-43l) = "-42 /-43 ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 'ld' *)
printf "\nlu positive\n%!";
test (sprintf "%lu" 42l = "42");
test (sprintf "%-4lu" 42l = "42 ");
test (sprintf "%04lu" 42l = "0042");
- test (sprintf "%+lu" 42l = "42");
- test (sprintf "% lu" 42l = "42");
- test (sprintf "%#lu" 42l = "42");
+ (*test (sprintf "%+lu" 42l = "42");*)
+ (* >> '+' is incompatible with 'lu' *)
+ (*test (sprintf "% lu" 42l = "42");*)
+ (* >> ' ' is incompatible with 'lu' *)
+ (*test (sprintf "%#lu" 42l = "42");*)
+ (* >> '#' is incompatible with 'lu' *)
test (sprintf "%4lu" 42l = " 42");
test (sprintf "%*lu" 4 42l = " 42");
- test (sprintf "%-0+ #6ld" 42l = "+42 ");
+ (*test (sprintf "%-0+ #6ld" 42l = "+42 ");*)
+ (* >> '-' is incompatible with '0', '#' is incompatible with 'ld' *)
printf "\nlu negative\n%!";
test (sprintf "%lu" (-1l) = "4294967295");
@@ -336,12 +387,15 @@ try
test (sprintf "%lx" 42l = "2a");
test (sprintf "%-4lx" 42l = "2a ");
test (sprintf "%04lx" 42l = "002a");
- test (sprintf "%+lx" 42l = "2a");
- test (sprintf "% lx" 42l = "2a");
+ (*test (sprintf "%+lx" 42l = "2a");*)
+ (* >> '+' is incompatible with 'lx' *)
+ (*test (sprintf "% lx" 42l = "2a");*)
+ (* >> ' ' is incompatible with 'lx' *)
test (sprintf "%#lx" 42l = "0x2a");
test (sprintf "%4lx" 42l = " 2a");
test (sprintf "%*lx" 5 42l = " 2a");
- test (sprintf "%-0+ #*lx" 5 42l = "0x2a ");
+ (*test (sprintf "%-0+ #*lx" 5 42l = "0x2a ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nlx negative\n%!";
test (sprintf "%lx" (-42l) = "ffffffd6");
@@ -350,12 +404,15 @@ try
test (sprintf "%lX" 42l = "2A");
test (sprintf "%-4lX" 42l = "2A ");
test (sprintf "%04lX" 42l = "002A");
- test (sprintf "%+lX" 42l = "2A");
- test (sprintf "% lX" 42l = "2A");
+ (*test (sprintf "%+lX" 42l = "2A");*)
+ (* >> '+' is incompatible with 'lX' *)
+ (*test (sprintf "% lX" 42l = "2A");*)
+ (* >> ' ' is incompatible with 'lX' *)
test (sprintf "%#lX" 42l = "0X2A");
test (sprintf "%4lX" 42l = " 2A");
test (sprintf "%*lX" 5 42l = " 2A");
- test (sprintf "%-0+ #*lX" 5 42l = "0X2A ");
+ (*test (sprintf "%-0+ #*lX" 5 42l = "0X2A ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nlx negative\n%!";
test (sprintf "%lX" (-42l) = "FFFFFFD6");
@@ -364,12 +421,15 @@ try
test (sprintf "%lo" 42l = "52");
test (sprintf "%-4lo" 42l = "52 ");
test (sprintf "%04lo" 42l = "0052");
- test (sprintf "%+lo" 42l = "52");
- test (sprintf "% lo" 42l = "52");
+ (*test (sprintf "%+lo" 42l = "52");*)
+ (* >> '+' is incompatible with 'lo' *)
+ (*test (sprintf "% lo" 42l = "52");*)
+ (* >> ' ' is incompatible with 'lo' *)
test (sprintf "%#lo" 42l = "052");
test (sprintf "%4lo" 42l = " 52");
test (sprintf "%*lo" 5 42l = " 52");
- test (sprintf "%-0+ #*lo" 5 42l = "052 ");
+ (*test (sprintf "%-0+ #*lo" 5 42l = "052 ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nlo negative\n%!";
test (sprintf "%lo" (-42l) = "37777777726");
@@ -381,34 +441,46 @@ try
test (sprintf "%Ld/%Li" 42L 43L = "42/43");
test (sprintf "%-4Ld/%-5Li" 42L 43L = "42 /43 ");
test (sprintf "%04Ld/%05Li" 42L 43L = "0042/00043");
- test (sprintf "%+Ld/%+Li" 42L 43L = "+42/+43");
- test (sprintf "% Ld/% Li" 42L 43L = " 42/ 43");
- test (sprintf "%#Ld/%#Li" 42L 43L = "42/43");
+ (*test (sprintf "%+Ld/%+Li" 42L 43L = "+42/+43");*)
+ (* >> '+' is incompatible with 'Ld' *)
+ (*test (sprintf "% Ld/% Li" 42L 43L = " 42/ 43");*)
+ (* >> ' ' is incompatible with 'Ld' *)
+ (*test (sprintf "%#Ld/%#Li" 42L 43L = "42/43");*)
+ (* >> '#' is incompatible with 'Ld' *)
test (sprintf "%4Ld/%5Li" 42L 43L = " 42/ 43");
test (sprintf "%*Ld/%*Li" 4 42L 5 43L = " 42/ 43");
- test (sprintf "%-0+#4Ld/%-0 #5Li" 42L 43L = "+42 / 43 ");
+ (*test (sprintf "%-0+#4Ld/%-0 #5Li" 42L 43L = "+42 / 43 ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nLd/Li negative\n%!";
test (sprintf "%Ld/%Li" (-42L) (-43L) = "-42/-43");
test (sprintf "%-4Ld/%-5Li" (-42L) (-43L) = "-42 /-43 ");
test (sprintf "%04Ld/%05Li" (-42L) (-43L) = "-042/-0043");
- test (sprintf "%+Ld/%+Li" (-42L) (-43L) = "-42/-43");
- test (sprintf "% Ld/% Li" (-42L) (-43L) = "-42/-43");
- test (sprintf "%#Ld/%#Li" (-42L) (-43L) = "-42/-43");
+ (*test (sprintf "%+Ld/%+Li" (-42L) (-43L) = "-42/-43");*)
+ (* >> '+' is incompatible with 'Ld' *)
+ (*test (sprintf "% Ld/% Li" (-42L) (-43L) = "-42/-43");*)
+ (* >> ' ' is incompatible with 'Ld' *)
+ (*test (sprintf "%#Ld/%#Li" (-42L) (-43L) = "-42/-43");*)
+ (* >> '#' is incompatible with 'Ld' *)
test (sprintf "%4Ld/%5Li" (-42L) (-43L) = " -42/ -43");
test (sprintf "%*Ld/%*Li" 4 (-42L) 5 (-43L) = " -42/ -43");
- test (sprintf "%-0+ #4Ld/%-0+ #5Li" (-42L) (-43L) = "-42 /-43 ");
+ (*test (sprintf "%-0+ #4Ld/%-0+ #5Li" (-42L) (-43L) = "-42 /-43 ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nLu positive\n%!";
test (sprintf "%Lu" 42L = "42");
test (sprintf "%-4Lu" 42L = "42 ");
test (sprintf "%04Lu" 42L = "0042");
- test (sprintf "%+Lu" 42L = "42");
- test (sprintf "% Lu" 42L = "42");
- test (sprintf "%#Lu" 42L = "42");
+ (*test (sprintf "%+Lu" 42L = "42");*)
+ (* >> '+' is incompatible with 'Lu' *)
+ (*test (sprintf "% Lu" 42L = "42");*)
+ (* >> ' ' is incompatible with 'Lu' *)
+ (*test (sprintf "%#Lu" 42L = "42");*)
+ (* >> '#' is incompatible with 'Lu' *)
test (sprintf "%4Lu" 42L = " 42");
test (sprintf "%*Lu" 4 42L = " 42");
- test (sprintf "%-0+ #6Ld" 42L = "+42 ");
+ (*test (sprintf "%-0+ #6Ld" 42L = "+42 ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nLu negative\n%!";
test (sprintf "%Lu" (-1L) = "18446744073709551615");
@@ -417,12 +489,15 @@ try
test (sprintf "%Lx" 42L = "2a");
test (sprintf "%-4Lx" 42L = "2a ");
test (sprintf "%04Lx" 42L = "002a");
- test (sprintf "%+Lx" 42L = "2a");
- test (sprintf "% Lx" 42L = "2a");
+ (*test (sprintf "%+Lx" 42L = "2a");*)
+ (* >> '+' is incompatible with 'Lx' *)
+ (*test (sprintf "% Lx" 42L = "2a");*)
+ (* >> ' ' is incompatible with 'Lx' *)
test (sprintf "%#Lx" 42L = "0x2a");
test (sprintf "%4Lx" 42L = " 2a");
test (sprintf "%*Lx" 5 42L = " 2a");
- test (sprintf "%-0+ #*Lx" 5 42L = "0x2a ");
+ (*test (sprintf "%-0+ #*Lx" 5 42L = "0x2a ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nLx negative\n%!";
test (sprintf "%Lx" (-42L) = "ffffffffffffffd6");
@@ -431,12 +506,15 @@ try
test (sprintf "%LX" 42L = "2A");
test (sprintf "%-4LX" 42L = "2A ");
test (sprintf "%04LX" 42L = "002A");
- test (sprintf "%+LX" 42L = "2A");
- test (sprintf "% LX" 42L = "2A");
+ (*test (sprintf "%+LX" 42L = "2A");*)
+ (* >> '+' is incompatible with 'LX' *)
+ (*test (sprintf "% LX" 42L = "2A");*)
+ (* >> ' ' is incompatible with 'LX' *)
test (sprintf "%#LX" 42L = "0X2A");
test (sprintf "%4LX" 42L = " 2A");
test (sprintf "%*LX" 5 42L = " 2A");
- test (sprintf "%-0+ #*LX" 5 42L = "0X2A ");
+ (*test (sprintf "%-0+ #*LX" 5 42L = "0X2A ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nLx negative\n%!";
test (sprintf "%LX" (-42L) = "FFFFFFFFFFFFFFD6");
@@ -445,12 +523,15 @@ try
test (sprintf "%Lo" 42L = "52");
test (sprintf "%-4Lo" 42L = "52 ");
test (sprintf "%04Lo" 42L = "0052");
- test (sprintf "%+Lo" 42L = "52");
- test (sprintf "% Lo" 42L = "52");
+ (*test (sprintf "%+Lo" 42L = "52");*)
+ (* >> '+' is incompatible with 'Lo' *)
+ (*test (sprintf "% Lo" 42L = "52");*)
+ (* >> ' ' is incompatible with 'Lo' *)
test (sprintf "%#Lo" 42L = "052");
test (sprintf "%4Lo" 42L = " 52");
test (sprintf "%*Lo" 5 42L = " 52");
- test (sprintf "%-0+ #*Lo" 5 42L = "052 ");
+ (*test (sprintf "%-0+ #*Lo" 5 42L = "052 ");*)
+ (* >> '-' is incompatible with '0' *)
printf "\nLo negative\n%!";
test (sprintf "%Lo" (-42L) = "1777777777777777777726");
@@ -471,7 +552,7 @@ try
printf "\n{...%%}\n%!";
let f = format_of_string "%4g/%s" in
- test (sprintf "%{%#0F%S%}" f = "%f%s");
+ test (sprintf "%{%.4F%5S%}" f = "%f%s");
printf "\n(...%%)\n%!";
let f = format_of_string "%d/foo/%s" in
diff --git a/testsuite/tests/lib-printf/tprintf.reference b/testsuite/tests/lib-printf/tprintf.reference
index 387dfb8533..11ee3a74fd 100644
--- a/testsuite/tests/lib-printf/tprintf.reference
+++ b/testsuite/tests/lib-printf/tprintf.reference
@@ -1,91 +1,91 @@
d/i positive
- 0 1 2 3 4 5 6 7 8
+ 0 1 2 3 4 5 6
d/i negative
- 9 10 11 12 13 14 15 16 17
+ 7 8 9 10 11 12 13
u positive
- 18 19 20 21 22 23 24 25 26
+ 14 15 16 17 18
u negative
- 27
+ 19
x positive
- 28 29 30 31 32 33 34 35 36
+ 20 21 22 23 24 25
x negative
- 37
+ 26
X positive
- 38 39 40 41 42 43 44 45 46
+ 27 28 29 30 31 32
x negative
- 47
+ 33
o positive
- 48 49 50 51 52 53 54 55 56
+ 34 35 36 37 38 39
o negative
- 57
+ 40
s
- 58 59 60 61 62 63 64 65 66 67 68 69 70 71
+ 41 42 43 44 45 46 47 48 49
S
- 72 73 74 75 76 77 78 79 80
+ 50 51 52 53 54 55
c
- 81 82 83 84
+ 56
C
- 85 86 87 88 89
+ 57 58
f
- 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107
+ 59 60 61 62 63 64 65 66 67 68 69 70 71 72
F
- 108 109 110 111
+ 73 74 75 76
e
- 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
+ 77 78 79 80 81 82 83 84 85 86 87 88 89 90
E
- 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
+ 91 92 93 94 95 96 97 98 99 100 101 102 103 104
B
- 148 149
+ 105 106
ld/li positive
- 150 151 152 153 154 155 156 157 158
+ 107 108 109 110 111 112 113
ld/li negative
- 159 160 161 162 163 164 165 166 167
+ 114 115 116 117 118 119 120
lu positive
- 168 169 170 171 172 173 174 175 176
+ 121 122 123 124 125
lu negative
- 177
+ 126
lx positive
- 178 179 180 181 182 183 184 185 186
+ 127 128 129 130 131 132
lx negative
- 187
+ 133
lX positive
- 188 189 190 191 192 193 194 195 196
+ 134 135 136 137 138 139
lx negative
- 197
+ 140
lo positive
- 198 199 200 201 202 203 204 205 206
+ 141 142 143 144 145 146
lo negative
- 207
+ 147
Ld/Li positive
- 208 209 210 211 212 213 214 215 216
+ 148 149 150 151 152
Ld/Li negative
- 217 218 219 220 221 222 223 224 225
+ 153 154 155 156 157
Lu positive
- 226 227 228 229 230 231 232 233 234
+ 158 159 160 161 162
Lu negative
- 235
+ 163
Lx positive
- 236 237 238 239 240 241 242 243 244
+ 164 165 166 167 168 169
Lx negative
- 245
+ 170
LX positive
- 246 247 248 249 250 251 252 253 254
+ 171 172 173 174 175 176
Lx negative
- 255
+ 177
Lo positive
- 256 257 258 259 260 261 262 263 264
+ 178 179 180 181 182 183
Lo negative
- 265
+ 184
a
- 266
+ 185
t
- 267
+ 186
{...%}
- 268
+ 187
(...%)
- 269
+ 188
! % @ , and constants
- 270 271 272 273 274 275 276
+ 189 190 191 192 193 194 195
end of tests
All tests succeeded.
diff --git a/testsuite/tests/lib-scanf/tscanf.ml b/testsuite/tests/lib-scanf/tscanf.ml
index 53c92ffc8d..8e6a252b86 100644
--- a/testsuite/tests/lib-scanf/tscanf.ml
+++ b/testsuite/tests/lib-scanf/tscanf.ml
@@ -1090,13 +1090,13 @@ let test46, test47 =
Printf.sprintf "%i %(%s%)."
1 "spells one, %s" "in english"),
(fun () ->
- Printf.sprintf "%i ,%{%s%}, %s."
+ Printf.sprintf "%i %{%s%}, %s."
1 "spells one %s" "in english")
;;
test (test46 () = "1 spells one, in english.")
;;
-test (test47 () = "1 ,%s, in english.")
+test (test47 () = "1 %s, in english.")
;;
(* Testing scanning of meta formats. *)
diff --git a/testsuite/tests/match-exception-warnings/Makefile b/testsuite/tests/match-exception-warnings/Makefile
new file mode 100644
index 0000000000..c9433b2ecb
--- /dev/null
+++ b/testsuite/tests/match-exception-warnings/Makefile
@@ -0,0 +1,15 @@
+#########################################################################
+# #
+# 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 Q Public License version 1.0. #
+# #
+#########################################################################
+
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.toplevel
+include $(BASEDIR)/makefiles/Makefile.common
diff --git a/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml b/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml
new file mode 100644
index 0000000000..742038db49
--- /dev/null
+++ b/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml
@@ -0,0 +1,12 @@
+(** Test exhaustiveness.
+
+ match clauses should continue to give warnings about inexhaustive
+ value-matching clauses when there is an exception-matching clause
+ *)
+
+let test_match_exhaustiveness () =
+ match None with
+ | exception e -> ()
+ | Some false -> ()
+ | None -> ()
+;;
diff --git a/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml.reference b/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml.reference
new file mode 100644
index 0000000000..f1e30bc56c
--- /dev/null
+++ b/testsuite/tests/match-exception-warnings/exhaustiveness_warnings.ml.reference
@@ -0,0 +1,11 @@
+
+# * * * * 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 value that is not matched:
+Some true
+val test_match_exhaustiveness : unit -> unit = <fun>
+#
diff --git a/testsuite/tests/match-exception/Makefile b/testsuite/tests/match-exception/Makefile
new file mode 100644
index 0000000000..299656b246
--- /dev/null
+++ b/testsuite/tests/match-exception/Makefile
@@ -0,0 +1,15 @@
+#########################################################################
+# #
+# 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 Q Public License version 1.0. #
+# #
+#########################################################################
+
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.several
+include $(BASEDIR)/makefiles/Makefile.common
diff --git a/testsuite/tests/match-exception/allocation.ml b/testsuite/tests/match-exception/allocation.ml
new file mode 100644
index 0000000000..fa943ffa3f
--- /dev/null
+++ b/testsuite/tests/match-exception/allocation.ml
@@ -0,0 +1,24 @@
+(** Test that matching multiple values doesn't allocate a block. *)
+
+let f x y =
+ match x, y with
+ | Some x, None
+ | None, Some x -> x + 1
+ | None, None -> 0
+ | Some x, Some y -> x + y
+ | exception _ -> -1
+
+let test_multiple_match_does_not_allocate =
+ let allocated_bytes = Gc.allocated_bytes () in
+ let allocated_bytes' = Gc.allocated_bytes () in
+ let a = Some 3 and b = None in
+ let allocated_bytes'' = Gc.allocated_bytes () in
+ let _ = f a b in
+ let allocated_bytes''' = Gc.allocated_bytes () in
+ if allocated_bytes' -. allocated_bytes = allocated_bytes''' -. allocated_bytes''
+ then
+ Printf.printf "no allocations for multiple-value match\n"
+ else
+ Printf.printf "multiple-value match allocated %f bytes\n"
+ ((allocated_bytes''' -. allocated_bytes'') -.
+ (allocated_bytes' -. allocated_bytes))
diff --git a/testsuite/tests/match-exception/allocation.reference b/testsuite/tests/match-exception/allocation.reference
new file mode 100644
index 0000000000..98056ce6e8
--- /dev/null
+++ b/testsuite/tests/match-exception/allocation.reference
@@ -0,0 +1 @@
+no allocations for multiple-value match
diff --git a/testsuite/tests/match-exception/exception_propagation.ml b/testsuite/tests/match-exception/exception_propagation.ml
new file mode 100644
index 0000000000..38d2cfd689
--- /dev/null
+++ b/testsuite/tests/match-exception/exception_propagation.ml
@@ -0,0 +1,17 @@
+(**
+ Test that match allows exceptions to propagate.
+*)
+let () =
+ try
+ match
+ (let _ = raise Not_found in
+ assert false)
+ with
+ | _ -> assert false
+ | exception Invalid_argument _ -> assert false
+ with
+ Not_found ->
+ print_endline "caught expected exception (Not_found)"
+ | _ ->
+ assert false
+;;
diff --git a/testsuite/tests/match-exception/exception_propagation.reference b/testsuite/tests/match-exception/exception_propagation.reference
new file mode 100644
index 0000000000..a119b6813e
--- /dev/null
+++ b/testsuite/tests/match-exception/exception_propagation.reference
@@ -0,0 +1 @@
+caught expected exception (Not_found)
diff --git a/testsuite/tests/match-exception/match_failure.ml b/testsuite/tests/match-exception/match_failure.ml
new file mode 100644
index 0000000000..c6149bf3bd
--- /dev/null
+++ b/testsuite/tests/match-exception/match_failure.ml
@@ -0,0 +1,19 @@
+(**
+ Test that value match failure in a match block raises Match_failure.
+*)
+let return_some_3 () = Some (1 + 2)
+;;
+
+let test_match_partial_match =
+ try
+ let _ = (match return_some_3 () with
+ | Some x when x < 3 -> "Some x"
+ | exception Failure _ -> "failure"
+ | exception Invalid_argument _ -> "invalid argument"
+ | None -> "None"
+ ) in
+ assert false
+ with
+ Match_failure _ ->
+ print_endline "match failure, as expected"
+;;
diff --git a/testsuite/tests/match-exception/match_failure.reference b/testsuite/tests/match-exception/match_failure.reference
new file mode 100644
index 0000000000..6e17840fe3
--- /dev/null
+++ b/testsuite/tests/match-exception/match_failure.reference
@@ -0,0 +1 @@
+match failure, as expected
diff --git a/testsuite/tests/match-exception/nested_handlers.ml b/testsuite/tests/match-exception/nested_handlers.ml
new file mode 100644
index 0000000000..0314cb103b
--- /dev/null
+++ b/testsuite/tests/match-exception/nested_handlers.ml
@@ -0,0 +1,45 @@
+(*
+ Test that multiple handlers coexist happily.
+*)
+
+let test_multiple_handlers =
+ let trace = ref [] in
+ let collect v = trace := v :: !trace in
+ let _ =
+ match
+ begin
+ match
+ begin
+ collect "one";
+ failwith "two"
+ end
+ with
+ () -> collect "failure one"
+ | exception (Failure x) ->
+ collect x;
+ failwith "three"
+ end
+ with
+ () ->
+ collect "failure two";
+ | exception (Failure x) ->
+ collect x;
+ match
+ begin
+ collect "four";
+ failwith "five"
+ end
+ with
+ () -> collect "failure three"
+ | exception (Failure x) ->
+ collect x
+ in
+ print_endline (String.concat " " !trace);
+ assert (!trace = [
+ "five";
+ "four";
+ "three";
+ "two";
+ "one";
+ ])
+;;
diff --git a/testsuite/tests/match-exception/nested_handlers.reference b/testsuite/tests/match-exception/nested_handlers.reference
new file mode 100644
index 0000000000..e305286698
--- /dev/null
+++ b/testsuite/tests/match-exception/nested_handlers.reference
@@ -0,0 +1 @@
+five four three two one
diff --git a/testsuite/tests/match-exception/raise_from_success_continuation.ml b/testsuite/tests/match-exception/raise_from_success_continuation.ml
new file mode 100644
index 0000000000..34fb647143
--- /dev/null
+++ b/testsuite/tests/match-exception/raise_from_success_continuation.ml
@@ -0,0 +1,15 @@
+(**
+ Test raising exceptions from a value-matching branch.
+*)
+let test_raise_from_val_handler =
+ let () = print_endline "test raise from val handler" in
+ let g () = List.find ((=)2) [1;2;4] in
+ let h () =
+ match
+ g ()
+ with exception _ -> 10
+ | _ -> raise Not_found
+ in
+ assert ((try h () with Not_found -> 20) = 20);
+ print_endline "raise from val handler succeeded"
+;;
diff --git a/testsuite/tests/match-exception/raise_from_success_continuation.reference b/testsuite/tests/match-exception/raise_from_success_continuation.reference
new file mode 100644
index 0000000000..4cfe216083
--- /dev/null
+++ b/testsuite/tests/match-exception/raise_from_success_continuation.reference
@@ -0,0 +1,2 @@
+test raise from val handler
+raise from val handler succeeded
diff --git a/testsuite/tests/match-exception/streams.ml b/testsuite/tests/match-exception/streams.ml
new file mode 100644
index 0000000000..42e9a5f1da
--- /dev/null
+++ b/testsuite/tests/match-exception/streams.ml
@@ -0,0 +1,37 @@
+(**
+ Test the stream example .
+*)
+type stream = Stream of (int * stream Lazy.t)
+;;
+
+exception End_of_stream
+;;
+
+let make_stream_up_to n =
+ let rec loop i =
+ if i = n then Stream (i, lazy (raise End_of_stream))
+ else Stream (i, lazy (loop (i + 1)))
+ in loop 0
+;;
+
+let stream_get (Stream (x, s)) = (x, Lazy.force s)
+;;
+
+let rec iter_stream_match f s =
+ match stream_get s
+ with exception End_of_stream -> ()
+ | (x, s') ->
+ begin
+ f x;
+ iter_stream_match f s'
+ end
+;;
+
+let test_iter_stream =
+ let limit = 10000000 in
+ try
+ iter_stream_match ignore (make_stream_up_to limit);
+ print_endline "iter_stream with handler case (match) is tail recursive"
+ with Stack_overflow ->
+ assert false
+;;
diff --git a/testsuite/tests/match-exception/streams.reference b/testsuite/tests/match-exception/streams.reference
new file mode 100644
index 0000000000..13df46408a
--- /dev/null
+++ b/testsuite/tests/match-exception/streams.reference
@@ -0,0 +1 @@
+iter_stream with handler case (match) is tail recursive
diff --git a/testsuite/tests/match-exception/tail_calls.ml b/testsuite/tests/match-exception/tail_calls.ml
new file mode 100644
index 0000000000..61cf026648
--- /dev/null
+++ b/testsuite/tests/match-exception/tail_calls.ml
@@ -0,0 +1,21 @@
+(**
+ The success continuation expression is in tail position.
+*)
+
+let count_to_tr_match n =
+ let rec loop i =
+ match
+ i < n
+ with exception Not_found -> ()
+ | false -> ()
+ | true -> loop (i + 1)
+ in loop 0
+;;
+
+let test_tail_recursion =
+ try
+ count_to_tr_match 10000000;
+ print_endline "handler-case (match) is tail recursive"
+ with _ ->
+ assert false
+;;
diff --git a/testsuite/tests/match-exception/tail_calls.reference b/testsuite/tests/match-exception/tail_calls.reference
new file mode 100644
index 0000000000..342bf24a29
--- /dev/null
+++ b/testsuite/tests/match-exception/tail_calls.reference
@@ -0,0 +1 @@
+handler-case (match) is tail recursive
diff --git a/testsuite/tests/regression/pr5757/pr5757.ml b/testsuite/tests/regression/pr5757/pr5757.ml
index 5395840c3b..3a40bb51f9 100644
--- a/testsuite/tests/regression/pr5757/pr5757.ml
+++ b/testsuite/tests/regression/pr5757/pr5757.ml
@@ -12,6 +12,6 @@
Random.init 3;;
for i = 0 to 100_000 do
- ignore (String.create (Random.int 1_000_000))
+ ignore (Bytes.create (Random.int 1_000_000))
done;;
Printf.printf "hello world\n";;
diff --git a/testsuite/tests/regression/pr6024/Makefile b/testsuite/tests/regression/pr6024/Makefile
index 964eefcedb..3426801f57 100644
--- a/testsuite/tests/regression/pr6024/Makefile
+++ b/testsuite/tests/regression/pr6024/Makefile
@@ -12,5 +12,6 @@
MAIN_MODULE=pr6024
-include ../../../makefiles/Makefile.one
-include ../../../makefiles/Makefile.common
+BASEDIR=../../..
+include $(BASEDIR)/makefiles/Makefile.one
+include $(BASEDIR)/makefiles/Makefile.common
diff --git a/testsuite/tests/tool-ocamldoc/odoc_test.ml b/testsuite/tests/tool-ocamldoc/odoc_test.ml
index 918cadc40f..9e34bb2a1c 100644
--- a/testsuite/tests/tool-ocamldoc/odoc_test.ml
+++ b/testsuite/tests/tool-ocamldoc/odoc_test.ml
@@ -53,7 +53,19 @@ class string_gen =
p fmt "# manifest (Odoc_info.string_of_type_expr):\n<[%s]>\n"
(match t.ty_manifest with
None -> "None"
- | Some e -> Odoc_info.string_of_type_expr e
+ | Some (Other e) -> Odoc_info.string_of_type_expr e
+ | Some (Object_type fields) ->
+ let b = Buffer.create 256 in
+ Buffer.add_string b "<";
+ List.iter
+ (fun fd ->
+ Printf.bprintf b " %s: %s ;"
+ fd.of_name
+ (Odoc_info.string_of_type_expr fd.of_type)
+ )
+ fields;
+ Buffer.add_string b " >";
+ Buffer.contents b
);
);
diff --git a/testsuite/tests/tool-ocamldoc/t01.ml b/testsuite/tests/tool-ocamldoc/t01.ml
index d253be43db..ee291b900b 100644
--- a/testsuite/tests/tool-ocamldoc/t01.ml
+++ b/testsuite/tests/tool-ocamldoc/t01.ml
@@ -16,4 +16,7 @@ module type MT = sig
(string * string * string) ->
(string * string * string) -> unit
val y : int
+
+ type obj_type =
+ < foo : int ; bar : float -> string ; gee : int -> (int * string) >
end
diff --git a/testsuite/tests/tool-ocamldoc/t01.reference b/testsuite/tests/tool-ocamldoc/t01.reference
index 72345ffecd..d5159bdfc9 100644
--- a/testsuite/tests/tool-ocamldoc/t01.reference
+++ b/testsuite/tests/tool-ocamldoc/t01.reference
@@ -23,6 +23,8 @@
string * string * string ->
string * string * string -> string * string * string -> unit
val y : int
+ type obj_type =
+ < bar : float -> string; foo : int; gee : int -> int * string >
end]>
# type T01.MT.t:
# manifest (Odoc_info.string_of_type_expr):
@@ -31,3 +33,6 @@ end]>
string ->
string * string * string ->
string * string * string -> string * string * string -> unit]>
+# type T01.MT.obj_type:
+# manifest (Odoc_info.string_of_type_expr):
+<[< bar: float -> string ; foo: int ; gee: int -> int * string ; >]>
diff --git a/testsuite/tests/typing-extensions/Makefile b/testsuite/tests/typing-extensions/Makefile
new file mode 100644
index 0000000000..5f42b70577
--- /dev/null
+++ b/testsuite/tests/typing-extensions/Makefile
@@ -0,0 +1,4 @@
+BASEDIR=../..
+include $(BASEDIR)/makefiles/Makefile.toplevel
+include $(BASEDIR)/makefiles/Makefile.common
+
diff --git a/testsuite/tests/typing-extensions/cast.ml b/testsuite/tests/typing-extensions/cast.ml
new file mode 100644
index 0000000000..afcc2080dc
--- /dev/null
+++ b/testsuite/tests/typing-extensions/cast.ml
@@ -0,0 +1,96 @@
+
+(* By using two types we can have a recursive constraint *)
+type 'a class_name = .. constraint 'a = < cast: 'a. 'a name -> 'a; ..>
+and 'a name = Class : 'a class_name -> (< cast: 'a. 'a name -> 'a; ..> as 'a) name
+;;
+
+exception Bad_cast
+;;
+
+class type castable =
+object
+ method cast: 'a.'a name -> 'a
+end
+;;
+
+(* Lets create a castable class with a name*)
+
+class type foo_t =
+object
+ inherit castable
+ method foo: string
+end
+;;
+
+type 'a class_name += Foo: foo_t class_name
+;;
+
+class foo: foo_t =
+object(self)
+ method cast: type a. a name -> a =
+ function
+ Class Foo -> (self :> foo_t)
+ | _ -> ((raise Bad_cast) : a)
+ method foo = "foo"
+end
+;;
+
+(* Now we can create a subclass of foo *)
+
+class type bar_t =
+object
+ inherit foo
+ method bar: string
+end
+;;
+
+type 'a class_name += Bar: bar_t class_name
+;;
+
+class bar: bar_t =
+object(self)
+ inherit foo as super
+ method cast: type a. a name -> a =
+ function
+ Class Bar -> (self :> bar_t)
+ | other -> super#cast other
+ method bar = "bar"
+end
+;;
+
+(* Now lets create a mutable list of castable objects *)
+
+let clist :castable list ref = ref []
+;;
+
+let push_castable (c: #castable) =
+ clist := (c :> castable) :: !clist
+;;
+
+let pop_castable () =
+ match !clist with
+ c :: rest ->
+ clist := rest;
+ c
+ | [] -> raise Not_found
+;;
+
+(* We can add foos and bars to this list, and retrive them *)
+
+push_castable (new foo);;
+push_castable (new bar);;
+push_castable (new foo);;
+
+let c1: castable = pop_castable ();;
+let c2: castable = pop_castable ();;
+let c3: castable = pop_castable ();;
+
+(* We can also downcast these values to foos and bars *)
+
+let f1: foo = c1#cast (Class Foo);; (* Ok *)
+let f2: foo = c2#cast (Class Foo);; (* Ok *)
+let f3: foo = c3#cast (Class Foo);; (* Ok *)
+
+let b1: bar = c1#cast (Class Bar);; (* Exception Bad_cast *)
+let b2: bar = c2#cast (Class Bar);; (* Ok *)
+let b3: bar = c3#cast (Class Bar);; (* Exception Bad_cast *)
diff --git a/testsuite/tests/typing-extensions/cast.ml.reference b/testsuite/tests/typing-extensions/cast.ml.reference
new file mode 100644
index 0000000000..c229741638
--- /dev/null
+++ b/testsuite/tests/typing-extensions/cast.ml.reference
@@ -0,0 +1,33 @@
+
+# type 'b class_name = .. constraint 'b = < cast : 'a. 'a name -> 'a; .. >
+and 'a name =
+ Class : 'a class_name -> (< cast : 'a0. 'a0 name -> 'a0; .. > as 'a) name
+# exception Bad_cast
+# class type castable = object method cast : 'a name -> 'a end
+# class type foo_t = object method cast : 'a name -> 'a method foo : string end
+# type 'b class_name += Foo : foo_t class_name
+# class foo : foo_t
+# class type bar_t =
+ object
+ method bar : string
+ method cast : 'a name -> 'a
+ method foo : string
+ end
+# type 'b class_name += Bar : bar_t class_name
+# class bar : bar_t
+# val clist : castable list ref = {contents = []}
+# val push_castable : #castable -> unit = <fun>
+# val pop_castable : unit -> castable = <fun>
+# - : unit = ()
+# - : unit = ()
+# - : unit = ()
+# val c1 : castable = <obj>
+# val c2 : castable = <obj>
+# val c3 : castable = <obj>
+# val f1 : foo = <obj>
+# val f2 : foo = <obj>
+# val f3 : foo = <obj>
+# Exception: Bad_cast.
+# val b2 : bar = <obj>
+# Exception: Bad_cast.
+#
diff --git a/testsuite/tests/typing-extensions/extensions.ml b/testsuite/tests/typing-extensions/extensions.ml
new file mode 100644
index 0000000000..59a23db9d0
--- /dev/null
+++ b/testsuite/tests/typing-extensions/extensions.ml
@@ -0,0 +1,321 @@
+
+type foo = ..
+;;
+
+type foo +=
+ A
+ | B of int
+;;
+
+let is_a x =
+ match x with
+ A -> true
+ | _ -> false
+;;
+
+(* The type must be open to create extension *)
+
+type foo
+;;
+
+type foo += A of int (* Error type is not open *)
+;;
+
+(* The type parameters must match *)
+
+type 'a foo = ..
+;;
+
+type ('a, 'b) foo += A of int (* Error: type parameter mismatch *)
+;;
+
+(* In a signature the type does not have to be open *)
+
+module type S =
+sig
+ type foo
+ type foo += A of float
+end
+;;
+
+(* But it must still be extensible *)
+
+module type S =
+sig
+ type foo = A of int
+ type foo += B of float (* Error foo does not have an extensible type *)
+end
+;;
+
+(* Signatures can change the grouping of extensions *)
+
+type foo = ..
+;;
+
+module M = struct
+ type foo +=
+ A of int
+ | B of string
+
+ type foo +=
+ C of int
+ | D of float
+end
+;;
+
+module type S = sig
+ type foo +=
+ B of string
+ | C of int
+
+ type foo += D of float
+
+ type foo += A of int
+end
+;;
+
+module M_S = (M : S)
+;;
+
+(* Extensions can be GADTs *)
+
+type 'a foo = ..
+;;
+
+type _ foo +=
+ A : int -> int foo
+ | B : int foo
+;;
+
+let get_num : type a. a foo -> a -> a option = fun f i1 ->
+ match f with
+ A i2 -> Some (i1 + i2)
+ | _ -> None
+;;
+
+(* Extensions must obey constraints *)
+
+type 'a foo = .. constraint 'a = [> `Var ]
+;;
+
+type 'a foo += A of 'a
+;;
+
+let a = A 9 (* ERROR: Constraints not met *)
+;;
+
+type 'a foo += B : int foo (* ERROR: Constraints not met *)
+;;
+
+(* Signatures can make an extension private *)
+
+type foo = ..
+;;
+
+module M = struct type foo += A of int end
+;;
+
+let a1 = M.A 10
+;;
+
+module type S = sig type foo += private A of int end
+;;
+
+module M_S = (M : S)
+;;
+
+let is_s x =
+ match x with
+ M_S.A _ -> true
+ | _ -> false
+;;
+
+let a2 = M_S.A 20 (* ERROR: Cannot create a value using a private constructor *)
+;;
+
+(* Extensions can be rebound *)
+
+type foo = ..
+;;
+
+module M = struct type foo += A1 of int end
+;;
+
+type foo += A2 = M.A1
+;;
+
+type bar = ..
+;;
+
+type bar += A3 = M.A1 (* Error: rebind wrong type *)
+;;
+
+module M = struct type foo += private B1 of int end
+;;
+
+type foo += private B2 = M.B1
+;;
+
+type foo += B3 = M.B1 (* Error: rebind private extension *)
+;;
+
+type foo += C = Unknown (* Error: unbound extension *)
+;;
+
+(* Extensions can be rebound even if type is closed *)
+
+module M : sig type foo type foo += A1 of int end
+ = struct type foo = .. type foo += A1 of int end
+
+type M.foo += A2 = M.A1
+
+(* Rebinding handles abbreviations *)
+
+type 'a foo = ..
+;;
+
+type 'a foo1 = 'a foo = ..
+;;
+
+type 'a foo2 = 'a foo = ..
+;;
+
+type 'a foo1 +=
+ A of int
+ | B of 'a
+ | C : int foo1
+;;
+
+type 'a foo2 +=
+ D = A
+ | E = B
+ | F = C
+;;
+
+(* Extensions must obey variances *)
+
+type +'a foo = ..
+;;
+
+type 'a foo += A of (int -> 'a)
+;;
+
+type 'a foo += B of ('a -> int) (* ERROR: Parameter variances are not satisfied *)
+;;
+
+type _ foo += C : ('a -> int) -> 'a foo (* ERROR: Parameter variances are not satisfied *)
+;;
+
+type 'a bar = ..
+;;
+
+type +'a bar += D of (int -> 'a) (* ERROR: type variances do not match *)
+;;
+
+(* Exceptions are compatible with extensions *)
+
+module M : sig
+ type exn +=
+ Foo of int * float
+ | Bar : 'a list -> exn
+end = struct
+ exception Bar : 'a list -> exn
+ exception Foo of int * float
+end
+;;
+
+module M : sig
+ exception Bar : 'a list -> exn
+ exception Foo of int * float
+end = struct
+ type exn +=
+ Foo of int * float
+ | Bar : 'a list -> exn
+end
+;;
+
+exception Foo of int * float
+;;
+
+exception Bar : 'a list -> exn
+;;
+
+module M : sig
+ type exn +=
+ Foo of int * float
+ | Bar : 'a list -> exn
+end = struct
+ exception Bar = Bar
+ exception Foo = Foo
+end
+;;
+
+(* Test toplevel printing *)
+
+type foo = ..
+;;
+
+type foo +=
+ Foo of int * int option
+ | Bar of int option
+;;
+
+let x = Foo(3, Some 4), Bar(Some 5) (* Prints Foo and Bar successfully *)
+;;
+
+type foo += Foo of string
+;;
+
+let y = x (* Prints Bar but not Foo (which has been shadowed) *)
+;;
+
+exception Foo of int * int option
+;;
+
+exception Bar of int option
+;;
+
+let x = Foo(3, Some 4), Bar(Some 5) (* Prints Foo and Bar successfully *)
+;;
+
+type foo += Foo of string
+;;
+
+let y = x (* Prints Bar and part of Foo (which has been shadowed) *)
+;;
+
+(* Test Obj functions *)
+
+type foo = ..
+;;
+
+type foo +=
+ Foo
+ | Bar of int
+;;
+
+let n1 = Obj.extension_name Foo
+;;
+
+let n2 = Obj.extension_name (Bar 1)
+;;
+
+let t = (Obj.extension_id (Bar 2)) = (Obj.extension_id (Bar 3)) (* true *)
+;;
+
+let f = (Obj.extension_id (Bar 2)) = (Obj.extension_id Foo) (* false *)
+;;
+
+let is_foo x = (Obj.extension_id Foo) = (Obj.extension_id x)
+
+type foo += Foo
+;;
+
+let f = is_foo Foo
+;;
+
+let _ = Obj.extension_name 7 (* Invald_arg *)
+;;
+
+let _ = Obj.extension_id (object method m = 3 end) (* Invald_arg *)
+;;
diff --git a/testsuite/tests/typing-extensions/extensions.ml.reference b/testsuite/tests/typing-extensions/extensions.ml.reference
new file mode 100644
index 0000000000..25af292de1
--- /dev/null
+++ b/testsuite/tests/typing-extensions/extensions.ml.reference
@@ -0,0 +1,131 @@
+
+# type foo = ..
+# type foo += A | B of int
+# val is_a : foo -> bool = <fun>
+# type foo
+# Characters 13-21:
+ type foo += A of int (* Error type is not open *)
+ ^^^^^^^^
+Error: Cannot extend type definition foo
+# type 'a foo = ..
+# Characters 1-30:
+ 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 type foo += A of float end
+# Characters 84-106:
+ type foo += B of float (* Error foo does not have an extensible type *)
+ ^^^^^^^^^^^^^^^^^^^^^^
+Error: Type foo is not extensible
+# type foo = ..
+# module M :
+ sig
+ type foo += A of int | B of string
+ type foo += C of int | D of float
+
+ end
+# module type S =
+ sig
+ type foo += B of string | C of int
+ type foo += D of float
+ type foo += A of int
+ end
+# module M_S : S
+# type 'a foo = ..
+# type _ foo += A : int -> int foo | B : int foo
+# val get_num : 'a foo -> 'a -> 'a option = <fun>
+# type 'a foo = .. constraint 'a = [> `Var ]
+# type 'a foo += A of 'a
+# Characters 11-12:
+ 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 *)
+ ^^^
+Error: This type int should be an instance of type [> `Var ]
+# type foo = ..
+# module M : sig type foo += A of int end
+# 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 = <fun>
+# Characters 10-18:
+ 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 *)
+ ^^^^
+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 *)
+ ^^^^
+Error: The constructor M.B1 is private
+# Characters 13-24:
+ type foo += C = Unknown (* Error: unbound extension *)
+ ^^^^^^^^^^^
+Error: Unbound constructor Unknown
+# module M : sig type foo type foo += A1 of int end
+type M.foo += A2 of int
+type 'a foo = ..
+# type 'a foo1 = 'a foo = ..
+# type 'a foo2 = 'a foo = ..
+# 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) (* ERROR: Parameter variances are not satisfied *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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 (* ERROR: Parameter variances are not satisfied *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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 *)
+ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+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
+# module M :
+ sig exception Bar : 'a list -> exn exception Foo of int * float end
+# exception Foo of int * float
+# exception Bar : 'a list -> exn
+# module M : sig type exn += Foo of int * float | Bar : 'a list -> exn end
+# type foo = ..
+# type foo += Foo of int * int option | Bar of int option
+# val x : foo * foo = (Foo (3, Some 4), Bar (Some 5))
+# type foo += Foo of string
+# val y : foo * foo = (<extension>, Bar (Some 5))
+# exception Foo of int * int option
+# exception Bar of int option
+# val x : exn * exn = (Foo (3, Some 4), Bar (Some 5))
+# type foo += Foo of string
+# val y : exn * exn = (Foo (3, _), Bar (Some 5))
+# type foo = ..
+# type foo += Foo | Bar of int
+# val n1 : string = "Foo"
+# val n2 : string = "Bar"
+# val t : bool = true
+# val f : bool = false
+# val is_foo : 'a -> bool = <fun>
+type foo += Foo
+# val f : bool = false
+# Exception: Invalid_argument "Obj.extension_name".
+# Exception: Invalid_argument "Obj.extension_id".
+#
diff --git a/testsuite/tests/typing-extensions/msg.ml b/testsuite/tests/typing-extensions/msg.ml
new file mode 100644
index 0000000000..ef1c12fb4c
--- /dev/null
+++ b/testsuite/tests/typing-extensions/msg.ml
@@ -0,0 +1,131 @@
+(* Typed names *)
+
+module Msg : sig
+
+ type 'a tag
+
+ type result = Result : 'a tag * 'a -> result
+
+ val write : 'a tag -> 'a -> unit
+
+ val read : unit -> result
+
+ type 'a tag += Int : int tag
+
+ module type Desc = sig
+ type t
+ val label : string
+ val write : t -> string
+ val read : string -> t
+ end
+
+ module Define (D : Desc) : sig
+ type 'a tag += C : D.t tag
+ end
+
+end = struct
+
+ type 'a tag = ..
+
+ type ktag = T : 'a tag -> ktag
+
+ type 'a kind =
+ { tag : 'a tag;
+ label : string;
+ write : 'a -> string;
+ read : string -> 'a; }
+
+ type rkind = K : 'a kind -> rkind
+
+ type wkind = { f : 'a . 'a tag -> 'a kind }
+
+ let readTbl : (string, rkind) Hashtbl.t = Hashtbl.create 13
+
+ let writeTbl : (ktag, wkind) Hashtbl.t = Hashtbl.create 13
+
+ let read_raw () : string * string = raise (Failure "Not implemented")
+
+ type result = Result : 'a tag * 'a -> result
+
+ let read () =
+ let label, content = read_raw () in
+ let K k = Hashtbl.find readTbl label in
+ let body = k.read content in
+ Result(k.tag, body)
+
+ let write_raw (label : string) (content : string) =
+ raise (Failure "Not implemented")
+
+ let write (tag : 'a tag) (body : 'a) =
+ let {f} = Hashtbl.find writeTbl (T tag) in
+ let k = f tag in
+ let content = k.write body in
+ write_raw k.label content
+
+ (* Add int kind *)
+
+ type 'a tag += Int : int tag
+
+ let ik =
+ { tag = Int;
+ label = "int";
+ write = string_of_int;
+ read = int_of_string }
+
+ let () = Hashtbl.add readTbl "int" (K ik)
+
+ let () =
+ let f (type t) (i : t tag) : t kind =
+ match i with
+ Int -> ik
+ | _ -> assert false
+ in
+ Hashtbl.add writeTbl (T Int) {f}
+
+ (* Support user defined kinds *)
+
+ module type Desc = sig
+ type t
+ val label : string
+ val write : t -> string
+ val read : string -> t
+ end
+
+ module Define (D : Desc) = struct
+ type 'a tag += C : D.t tag
+ let k =
+ { tag = C;
+ label = D.label;
+ write = D.write;
+ read = D.read }
+ let () = Hashtbl.add readTbl D.label (K k)
+ let () =
+ let f (type t) (c : t tag) : t kind =
+ match c with
+ C -> k
+ | _ -> assert false
+ in
+ Hashtbl.add writeTbl (T C) {f}
+ end
+
+end;;
+
+let write_int i = Msg.write Msg.Int i;;
+
+module StrM = Msg.Define(struct
+ type t = string
+ let label = "string"
+ let read s = s
+ let write s = s
+end);;
+
+type 'a Msg.tag += String = StrM.C;;
+
+let write_string s = Msg.write String s;;
+
+let read_one () =
+ let Msg.Result(tag, body) = Msg.read () in
+ match tag with
+ Msg.Int -> print_int body
+ | String -> print_string body
+ | _ -> print_string "Unknown";;
diff --git a/testsuite/tests/typing-extensions/msg.ml.reference b/testsuite/tests/typing-extensions/msg.ml.reference
new file mode 100644
index 0000000000..e7f1a8f248
--- /dev/null
+++ b/testsuite/tests/typing-extensions/msg.ml.reference
@@ -0,0 +1,23 @@
+
+# module Msg :
+ sig
+ type 'a tag
+ type result = Result : 'a tag * 'a -> result
+ val write : 'a tag -> 'a -> unit
+ val read : unit -> result
+ type 'a tag += Int : int tag
+ module type Desc =
+ sig
+ type t
+ val label : string
+ val write : t -> string
+ val read : string -> t
+ end
+ module Define : functor (D : Desc) -> sig type 'a tag += C : D.t tag end
+ end
+# val write_int : int -> unit = <fun>
+# module StrM : sig type 'a Msg.tag += C : string Msg.tag end
+# type 'a Msg.tag += String : string Msg.tag
+# val write_string : string -> unit = <fun>
+# val read_one : unit -> unit = <fun>
+#
diff --git a/testsuite/tests/typing-extensions/open_types.ml b/testsuite/tests/typing-extensions/open_types.ml
new file mode 100644
index 0000000000..e7632cac29
--- /dev/null
+++ b/testsuite/tests/typing-extensions/open_types.ml
@@ -0,0 +1,109 @@
+type foo = ..
+;;
+
+(* Check that abbreviations work *)
+
+type bar = foo = ..
+;;
+
+type baz = foo = ..
+;;
+
+type bar += Bar1 of int
+;;
+
+type baz += Bar2 of int
+;;
+
+module M = struct type bar += Foo of float end
+;;
+
+module type S = sig type baz += Foo of float end
+;;
+
+module M_S = (M : S)
+;;
+
+(* Abbreviations need to be made open *)
+
+type foo = ..
+;;
+
+type bar = foo
+;;
+
+type bar += Bar of int (* Error: type is not open *)
+;;
+
+type baz = bar = .. (* Error: type kinds don't match *)
+;;
+
+(* Abbreviations need to match parameters *)
+
+type 'a foo = ..
+;;
+
+type ('a, 'b) bar = 'a foo = .. (* Error: arrities do not match *)
+;;
+
+type ('a, 'b) foo = ..
+;;
+
+type ('a, 'b) bar = ('a, 'a) foo = .. (* Error: constraints do not match *)
+;;
+
+(* Private abstract types cannot be open *)
+
+type foo = ..
+;;
+
+type bar = private foo = .. (* ERROR: Private abstract types cannot be open *)
+;;
+
+(* Check that signatures can hide open-ness *)
+
+module M = struct type foo = .. end
+;;
+
+module type S = sig type foo end
+;;
+
+module M_S = (M : S)
+;;
+
+type M_S.foo += Foo (* ERROR: Cannot extend a type that isn't "open" *)
+;;
+
+(* Check that signatures cannot add open-ness *)
+
+module M = struct type foo end
+;;
+
+module type S = sig type foo = .. end
+;;
+
+module M_S = (M : S) (* ERROR: Signatures are not compatible *)
+;;
+
+(* Check that signatures maintain variances *)
+
+module M = struct type +'a foo = .. type 'a bar = 'a foo = .. end
+;;
+
+module type S = sig type 'a foo = .. type 'a bar = 'a foo = .. end
+;;
+
+module M_S = (M : S) (* ERROR: Signatures are not compatible *)
+;;
+
+(* Exn is an open type *)
+
+type exn2 = exn = ..
+;;
+
+(* Exhaustiveness *)
+
+type foo = ..
+type foo += Foo
+let f = function Foo -> ()
+;; (* warn *)
diff --git a/testsuite/tests/typing-extensions/open_types.ml.reference b/testsuite/tests/typing-extensions/open_types.ml.reference
new file mode 100644
index 0000000000..5fb9684d47
--- /dev/null
+++ b/testsuite/tests/typing-extensions/open_types.ml.reference
@@ -0,0 +1,83 @@
+
+# type foo = ..
+# type bar = foo = ..
+# type baz = foo = ..
+# type bar += Bar1 of int
+# type baz += Bar2 of int
+# module M : sig type bar += Foo of float end
+# module type S = sig type baz += Foo of float end
+# module M_S : S
+# type foo = ..
+# type bar = foo
+# Characters 13-23:
+ type bar += Bar of int (* Error: type is not open *)
+ ^^^^^^^^^^
+Error: Cannot extend type definition bar
+# Characters 6-20:
+ 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 6-32:
+ 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 6-38:
+ 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.
+# type foo = ..
+# Characters 24-25:
+ type bar = private foo = .. (* ERROR: Private abstract types cannot be open *)
+ ^
+Error: Syntax error
+# module M : sig type foo = .. end
+# module type S = sig type foo end
+# module M_S : S
+# Characters 17-20:
+ type M_S.foo += Foo (* ERROR: Cannot extend a type that isn't "open" *)
+ ^^^
+Error: Cannot extend type definition M_S.foo
+# 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 *)
+ ^
+Error: Signature mismatch:
+ Modules do not match: sig type foo = M.foo end is not included in S
+ Type declarations do not match:
+ type foo = M.foo
+ is not included in
+ type foo = ..
+ Their kinds differ.
+# 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 *)
+ ^
+Error: Signature mismatch:
+ Modules do not match:
+ sig type 'a foo = 'a M.foo = .. type 'a bar = 'a foo = .. end
+ is not included in
+ S
+ Type declarations do not match:
+ type 'a foo = 'a M.foo = ..
+ is not included in
+ type 'a foo = ..
+ Their variances do not agree.
+# type exn2 = exn = ..
+# Characters 61-79:
+ let f = function Foo -> ()
+ ^^^^^^^^^^^^^^^^^^
+Warning 8: this pattern-matching is not exhaustive.
+Here is an example of a value that is not matched:
+*extension*
+type foo = ..
+type foo += Foo
+val f : foo -> unit = <fun>
+#
diff --git a/testsuite/tests/typing-gadts/pr6174.ml.principal.reference b/testsuite/tests/typing-gadts/pr6174.ml.principal.reference
index 647015c367..8f2be5252c 100644
--- a/testsuite/tests/typing-gadts/pr6174.ml.principal.reference
+++ b/testsuite/tests/typing-gadts/pr6174.ml.principal.reference
@@ -1,8 +1,7 @@
-# Characters 118-119:
+# Characters 137-138:
fun C k -> k (fun x -> x);;
- ^
-Error: Recursive local constraint when unifying
- (((ex#0 -> ex#1) -> ex#1) -> (ex#2 -> ex#1) -> ex#1) t
- with ((a -> o) -> o) t
+ ^
+Error: This expression has type ex#0 but an expression was expected of type
+ ex#1 = (ex#2 -> ex#1) -> ex#1
#
diff --git a/testsuite/tests/typing-gadts/pr6174.ml.reference b/testsuite/tests/typing-gadts/pr6174.ml.reference
index 647015c367..8f2be5252c 100644
--- a/testsuite/tests/typing-gadts/pr6174.ml.reference
+++ b/testsuite/tests/typing-gadts/pr6174.ml.reference
@@ -1,8 +1,7 @@
-# Characters 118-119:
+# Characters 137-138:
fun C k -> k (fun x -> x);;
- ^
-Error: Recursive local constraint when unifying
- (((ex#0 -> ex#1) -> ex#1) -> (ex#2 -> ex#1) -> ex#1) t
- with ((a -> o) -> o) t
+ ^
+Error: This expression has type ex#0 but an expression was expected of type
+ ex#1 = (ex#2 -> ex#1) -> ex#1
#
diff --git a/testsuite/tests/typing-gadts/test.ml b/testsuite/tests/typing-gadts/test.ml
index a8215290ad..2f0bb91962 100644
--- a/testsuite/tests/typing-gadts/test.ml
+++ b/testsuite/tests/typing-gadts/test.ml
@@ -102,12 +102,8 @@ module Existential_escape =
module Rectype =
struct
type (_,_) t = C : ('a,'a) t
- let _ =
- fun (type s) ->
- let a : (s, s * s) t = failwith "foo" in
- match a with
- C ->
- ()
+ let f : type s. (s, s*s) t -> unit =
+ fun C -> () (* here s = s*s! *)
end
;;
diff --git a/testsuite/tests/typing-gadts/test.ml.principal.reference b/testsuite/tests/typing-gadts/test.ml.principal.reference
index 0d40f674a5..fd9fb3501c 100644
--- a/testsuite/tests/typing-gadts/test.ml.principal.reference
+++ b/testsuite/tests/typing-gadts/test.ml.principal.reference
@@ -53,10 +53,8 @@ module Nonexhaustive :
Error: This expression has type a#2 t but an expression was expected of type
a#2 t
The type constructor a#2 would escape its scope
-# Characters 174-175:
- C ->
- ^
-Error: Recursive local constraint when unifying (s, s) t with (s, s * s) t
+# module Rectype :
+ sig type (_, _) t = C : ('a, 'a) t val f : ('s, 's * 's) t -> unit end
# Characters 178-186:
| (IntLit _ | BoolLit _) -> ()
^^^^^^^^
diff --git a/testsuite/tests/typing-gadts/test.ml.reference b/testsuite/tests/typing-gadts/test.ml.reference
index e6aa47b415..a5faa02c01 100644
--- a/testsuite/tests/typing-gadts/test.ml.reference
+++ b/testsuite/tests/typing-gadts/test.ml.reference
@@ -53,10 +53,8 @@ module Nonexhaustive :
Error: This expression has type a#2 t but an expression was expected of type
a#2 t
The type constructor a#2 would escape its scope
-# Characters 174-175:
- C ->
- ^
-Error: Recursive local constraint when unifying (s, s) t with (s, s * s) t
+# module Rectype :
+ sig type (_, _) t = C : ('a, 'a) t val f : ('s, 's * 's) t -> unit end
# Characters 178-186:
| (IntLit _ | BoolLit _) -> ()
^^^^^^^^
diff --git a/testsuite/tests/typing-modules/Test.ml b/testsuite/tests/typing-modules/Test.ml
index e5cbe9f395..97ef3f1687 100644
--- a/testsuite/tests/typing-modules/Test.ml
+++ b/testsuite/tests/typing-modules/Test.ml
@@ -54,3 +54,8 @@ module type B = A with type t = u;; (* fail *)
(* PR#5815 *)
module type S = sig exception Foo of int exception Foo of bool end;;
+
+(* PR#6410 *)
+
+module F(X : sig end) = struct let x = 3 end;;
+F.x;; (* fail *)
diff --git a/testsuite/tests/typing-modules/Test.ml.principal.reference b/testsuite/tests/typing-modules/Test.ml.principal.reference
index 8e993fa3aa..d99e9a3cd3 100644
--- a/testsuite/tests/typing-modules/Test.ml.principal.reference
+++ b/testsuite/tests/typing-modules/Test.ml.principal.reference
@@ -29,4 +29,9 @@ Error: Signature mismatch:
Error: This variant or record definition does not match that of type u
The types for field X are not equal.
# module type S = sig exception Foo of bool end
+# module F : functor (X : sig end) -> sig val x : int end
+# Characters 0-3:
+ F.x;; (* fail *)
+ ^^^
+Error: The module F is a functor, not a structure
#
diff --git a/testsuite/tests/typing-modules/Test.ml.reference b/testsuite/tests/typing-modules/Test.ml.reference
index 8e993fa3aa..d99e9a3cd3 100644
--- a/testsuite/tests/typing-modules/Test.ml.reference
+++ b/testsuite/tests/typing-modules/Test.ml.reference
@@ -29,4 +29,9 @@ Error: Signature mismatch:
Error: This variant or record definition does not match that of type u
The types for field X are not equal.
# module type S = sig exception Foo of bool end
+# module F : functor (X : sig end) -> sig val x : int end
+# Characters 0-3:
+ F.x;; (* fail *)
+ ^^^
+Error: The module F is a functor, not a structure
#
diff --git a/testsuite/tests/typing-modules/aliases.ml b/testsuite/tests/typing-modules/aliases.ml
index a65812e4bb..b77b0c47db 100644
--- a/testsuite/tests/typing-modules/aliases.ml
+++ b/testsuite/tests/typing-modules/aliases.ml
@@ -204,3 +204,19 @@ module type Alias = sig module N : sig end module M = N end;;
module F (X : sig end) = struct type t end;;
module type A = Alias with module N := F(List);;
module rec Bad : A = Bad;;
+
+(* Shinwell 2014-04-23 *)
+module B = struct
+ module R = struct
+ type t = string
+ end
+
+ module O = R
+end
+
+module K = struct
+ module E = B
+ module N = E.O
+end;;
+
+let x : K.N.t = "foo";;
diff --git a/testsuite/tests/typing-modules/aliases.ml.reference b/testsuite/tests/typing-modules/aliases.ml.reference
index d31516b987..e820b78e28 100644
--- a/testsuite/tests/typing-modules/aliases.ml.reference
+++ b/testsuite/tests/typing-modules/aliases.ml.reference
@@ -371,4 +371,7 @@ Error: Module type declarations do not match:
module rec Bad : A = Bad;;
^
Error: Unbound module type A
+# module B : sig module R : sig type t = string end module O = R end
+module K : sig module E = B module N = E.O end
+# val x : K.N.t = "foo"
#
diff --git a/testsuite/tests/typing-objects/Tests.ml.principal.reference b/testsuite/tests/typing-objects/Tests.ml.principal.reference
index 76ade67556..4821b58781 100644
--- a/testsuite/tests/typing-objects/Tests.ml.principal.reference
+++ b/testsuite/tests/typing-objects/Tests.ml.principal.reference
@@ -244,9 +244,9 @@ Error: Signature mismatch:
val f : (#c as 'a) -> 'a
is not included in
val f : #c -> #c
-# Characters 32-55:
+# Characters 38-39:
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.
# - : < m : (< m : 'a > as 'b) -> 'b as 'a; .. > -> 'b = <fun>
@@ -295,12 +295,12 @@ Warning 10: this expression should have type unit.
unit -> object method private m : int method n : int method o : int end
# - : int * int = (1, 1)
# class c : unit -> object method m : int end
-# - : int = 95
-# - : int = 96
-# - : int = 97
-# - : int * int * int = (98, 99, 100)
-# - : int * int * int * int * int = (101, 102, 103, 33, 33)
-# - : int * int * int * int * int = (104, 105, 106, 33, 33)
+# - : int = 100
+# - : int = 101
+# - : int = 102
+# - : int * int * int = (103, 104, 105)
+# - : int * int * int * int * int = (106, 107, 108, 33, 33)
+# - : int * int * int * int * int = (109, 110, 111, 33, 33)
# Characters 42-69:
class a = let _ = new b in object end
^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/testsuite/tests/typing-objects/Tests.ml.reference b/testsuite/tests/typing-objects/Tests.ml.reference
index 97ed42ca7d..25ab6d86c6 100644
--- a/testsuite/tests/typing-objects/Tests.ml.reference
+++ b/testsuite/tests/typing-objects/Tests.ml.reference
@@ -244,9 +244,9 @@ Error: Signature mismatch:
val f : (#c as 'a) -> 'a
is not included in
val f : #c -> #c
-# Characters 32-55:
+# Characters 38-39:
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.
# - : < m : (< m : 'a > as 'b) -> 'b as 'a; .. > -> 'b = <fun>
@@ -294,12 +294,12 @@ Warning 10: this expression should have type unit.
unit -> object method private m : int method n : int method o : int end
# - : int * int = (1, 1)
# class c : unit -> object method m : int end
-# - : int = 95
-# - : int = 96
-# - : int = 97
-# - : int * int * int = (98, 99, 100)
-# - : int * int * int * int * int = (101, 102, 103, 33, 33)
-# - : int * int * int * int * int = (104, 105, 106, 33, 33)
+# - : int = 100
+# - : int = 101
+# - : int = 102
+# - : int * int * int = (103, 104, 105)
+# - : int * int * int * int * int = (106, 107, 108, 33, 33)
+# - : int * int * int * int * int = (109, 110, 111, 33, 33)
# Characters 42-69:
class a = let _ = new b in object end
^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/testsuite/tests/typing-objects/pr6383.ml b/testsuite/tests/typing-objects/pr6383.ml
new file mode 100644
index 0000000000..bd2fdb06f0
--- /dev/null
+++ b/testsuite/tests/typing-objects/pr6383.ml
@@ -0,0 +1 @@
+let f (x: #M.foo) = 0;;
diff --git a/testsuite/tests/typing-objects/pr6383.ml.reference b/testsuite/tests/typing-objects/pr6383.ml.reference
new file mode 100644
index 0000000000..01b6141d3f
--- /dev/null
+++ b/testsuite/tests/typing-objects/pr6383.ml.reference
@@ -0,0 +1,6 @@
+
+# Characters 10-16:
+ let f (x: #M.foo) = 0;;
+ ^^^^^^
+Error: Unbound module M
+#
diff --git a/testsuite/tests/typing-warnings/coercions.ml.principal.reference b/testsuite/tests/typing-warnings/coercions.ml.principal.reference
index d950e231fc..d5397bf05e 100644
--- a/testsuite/tests/typing-warnings/coercions.ml.principal.reference
+++ b/testsuite/tests/typing-warnings/coercions.ml.principal.reference
@@ -7,7 +7,9 @@ Warning 18: this coercion to format6 is not principal.
# 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
+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 = <fun>
#
diff --git a/testsuite/tests/typing-warnings/coercions.ml.reference b/testsuite/tests/typing-warnings/coercions.ml.reference
index 2ab458b682..f442130510 100644
--- a/testsuite/tests/typing-warnings/coercions.ml.reference
+++ b/testsuite/tests/typing-warnings/coercions.ml.reference
@@ -3,7 +3,9 @@
# 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
+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 = <fun>
#
diff --git a/testsuite/typing b/testsuite/typing
index ff3818c1ce..cb953d6ac0 100644
--- a/testsuite/typing
+++ b/testsuite/typing
@@ -1,3 +1,4 @@
+tests/typing-extensions
tests/typing-fstclassmod
tests/typing-gadts
tests/typing-implicit_unpack
diff --git a/tools/.depend b/tools/.depend
index a058ee37f3..ea66ede860 100644
--- a/tools/.depend
+++ b/tools/.depend
@@ -28,15 +28,13 @@ depend.cmx : ../parsing/parsetree.cmi ../utils/misc.cmx \
../parsing/longident.cmx ../parsing/location.cmx ../parsing/asttypes.cmi \
depend.cmi
dumpobj.cmo : ../utils/tbl.cmi opnames.cmo ../bytecomp/opcodes.cmo \
- ../utils/misc.cmi ../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
+ ../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 \
- ../utils/misc.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
+ ../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 \
diff --git a/tools/Makefile.shared b/tools/Makefile.shared
index 6b33a5b047..251743449f 100644
--- a/tools/Makefile.shared
+++ b/tools/Makefile.shared
@@ -13,12 +13,12 @@
include ../config/Makefile
CAMLRUN=../boot/ocamlrun
-CAMLC=$(CAMLRUN) ../boot/ocamlc -strict-sequence -nostdlib -I ../boot
+CAMLC=$(CAMLRUN) ../boot/ocamlc -nostdlib -I ../boot
CAMLOPT=$(CAMLRUN) ../ocamlopt -nostdlib -I ../stdlib
CAMLLEX=$(CAMLRUN) ../boot/ocamllex
INCLUDES=-I ../utils -I ../parsing -I ../typing -I ../bytecomp -I ../asmcomp \
-I ../driver -I ../toplevel
-COMPFLAGS= -w +32..39 -warn-error A $(INCLUDES)
+COMPFLAGS= -strict-sequence -w +27+32..39 -warn-error A -safe-string $(INCLUDES)
LINKFLAGS=$(INCLUDES)
all: ocamldep ocamlprof ocamlcp ocamloptp ocamlmktop ocamlmklib dumpobj \
@@ -39,7 +39,7 @@ CAMLDEP_OBJ=depend.cmo ocamldep.cmo
CAMLDEP_IMPORTS=misc.cmo config.cmo clflags.cmo terminfo.cmo \
warnings.cmo location.cmo longident.cmo \
syntaxerr.cmo ast_helper.cmo parser.cmo lexer.cmo parse.cmo \
- ccomp.cmo pparse.cmo compenv.cmo
+ ccomp.cmo ast_mapper.cmo pparse.cmo compenv.cmo
ocamldep: depend.cmi $(CAMLDEP_OBJ)
$(CAMLC) $(LINKFLAGS) -compat-32 -o ocamldep $(CAMLDEP_IMPORTS) $(CAMLDEP_OBJ)
@@ -264,7 +264,7 @@ opnames.ml: ../byterun/instruct.h
sed -e '/\/\*/d' \
-e '/^#/d' \
-e 's/enum \(.*\) {/let names_of_\1 = [|/' \
- -e 's/};$$/ |]/' \
+ -e 's/.*};$$/ |]/' \
-e 's/\([A-Z][A-Z_0-9a-z]*\)/"\1"/g' \
-e 's/,/;/g' \
../byterun/instruct.h > opnames.ml
diff --git a/tools/check-typo b/tools/check-typo
index 93814131e5..ea7c63f775 100755
--- a/tools/check-typo
+++ b/tools/check-typo
@@ -23,6 +23,7 @@
# - absence of empty lines at end of file (white-at-eof)
# - presence of a LF character at the end of the file (missing-lf)
# - maximum line length of 80 characters (long-line)
+# - maximum line length of 132 characters (very-long-line)
# - presence of a copyright header (missing-header)
# - absence of a leftover "$Id" string (svn-keyword)
@@ -49,6 +50,9 @@
# *.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.
@@ -130,14 +134,15 @@ IGNORE_DIRS="
svnrules=`svn propget ocaml:typo "$f"`
fi
rules="$userrules"
+ add_hd(){ rules="missing-header,$rules"; }
case "$f" in
Makefile*|*/Makefile*) rules="tab,$rules";;
+ */.depend*|*/.ignore) add_hd;;
+ *.mlpack|*.mllib|*.mltop|*.odocl|*.itarget|*.clib) add_hd;;
+ *.reference|*/reference) continue;;
esac
- h(){ rules="missing-header,$rules"; }
case "$f" in
- */.depend*|*/.ignore) h;;
- *.mlpack|*.mllib|*.mltop|*.odocl|*.itarget|*.clib) h;;
- *.reference|*/reference) continue;;
+ ocamldoc/*|*/ocamldoc/*) rules="long-line,$rules";;
esac
(cat "$f"; echo) \
@@ -182,6 +187,12 @@ IGNORE_DIRS="
err("long-line", "line is over 80 characters");
}
+ length($0) > 132 {
+ RSTART = 133;
+ RLENGTH = 0;
+ err("very-long-line", "line is over 132 characters");
+ }
+
3 <= NR && NR <= 5 \
&& (/ OCaml / || / ocamlbuild / || / OCamldoc /) {
header_ocaml = NR;
diff --git a/tools/ci-build b/tools/ci-build
new file mode 100755
index 0000000000..4bb2593eb6
--- /dev/null
+++ b/tools/ci-build
@@ -0,0 +1,159 @@
+#!/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 Q Public License version 1.0. #
+# #
+#########################################################################
+
+# This script is run on our continuous-integration servers to recompile
+# from scratch and run the test suite.
+
+# arguments:
+# 1. architecture: bsd, macos, linux, cygwin, mingw, mingw64, msvc, msvc64
+# 2. directory in which to build (trunk, 4.02, etc)
+# for windows, this is relative to $HOME/jenkins-workspace
+# for bsd, macos, linux, this is "." or an absolute directory
+# 3. options:
+# -conf configure-option
+# -patch1 file-name apply patch with -p1
+
+error () {
+ echo "$1" >&2
+ exit 3
+}
+
+#########################################################################
+# be verbose
+set -x
+
+#########################################################################
+# "Parse" mandatory command-line arguments.
+
+arch="$1"
+branch="$2"
+shift 2
+
+#########################################################################
+# If we are called from a Windows batch script, we must set up the
+# Unix environment variables (e.g. PATH).
+
+case "$arch" in
+ bsd|macos|linux) ;;
+ cygwin|mingw|mingw64)
+ . /etc/profile
+ . "$HOME/.profile"
+ ;;
+ msvc)
+ . /etc/profile
+ . "$HOME/.profile"
+ . "$HOME/.msenv32"
+ ;;
+ msvc64)
+ . /etc/profile
+ . "$HOME/.profile"
+ . "$HOME/.msenv64"
+ ;;
+ *) error "unknown architecture: $arch";;
+esac
+
+#########################################################################
+
+# be verbose and stop on error
+set -ex
+
+#########################################################################
+# set up variables
+
+# default values
+make=make
+instdir="$HOME/ocaml-tmp-install"
+workdir="$branch"
+docheckout=false
+nt=
+
+case "$arch" in
+ bsd)
+ make=gmake
+ ;;
+ macos) ;;
+ linux) ;;
+ cygwin)
+ workdir="$HOME/jenkins-workspace/$branch"
+ docheckout=true
+ ;;
+ mingw)
+ instdir=/cygdrive/c/ocamlmgw
+ workdir="$HOME/jenkins-workspace/$branch"
+ docheckout=true
+ nt=.nt
+ ;;
+ mingw64)
+ instdir=/cygdrive/c/ocamlmgw64
+ workdir="$HOME/jenkins-workspace/$branch"
+ docheckout=true
+ nt=.nt
+ ;;
+ msvc)
+ instdir=/cygdrive/c/ocamlms
+ workdir="$HOME/jenkins-workspace/$branch"
+ docheckout=true
+ nt=.nt
+ ;;
+ msvc64)
+ instdir=/cygdrive/c/ocamlms64
+ workdir="$HOME/jenkins-workspace/$branch"
+ docheckout=true
+ nt=.nt
+ ;;
+ *) error "unknown architecture: $arch";;
+esac
+
+#########################################################################
+# Go to the right directory
+
+cd "$workdir"
+
+#########################################################################
+# parse optional command-line arguments (has to be done after the "cd")
+# Configure options are not allowed to have spaces or special characters
+# for the moment. We'll fix that when needed.
+confoptions=""
+while [ $# -gt 0 ]; do
+ case $1 in
+ -conf) confoptions="$confoptions $2"; shift 2;;
+ -patch1) patch -f -p1 <"$2"; shift 2;;
+ *) error "unknown option $1";;
+ esac
+done
+
+#########################################################################
+# Do the work
+
+$make -f Makefile$nt distclean || :
+
+if $docheckout; then
+ svn update --accept theirs-full
+fi
+
+case $nt in
+ "") ./configure -prefix "$instdir" $confoptions;;
+ .nt)
+ cp config/m-nt.h config/m.h
+ cp config/s-nt.h config/s.h
+ cp config/Makefile.$arch config/Makefile
+ ;;
+ *) error "internal error";;
+esac
+
+$make -f Makefile$nt world.opt
+$make -f Makefile$nt install
+
+rm -rf "$instdir"
+cd testsuite
+$make all
diff --git a/tools/cmt2annot.ml b/tools/cmt2annot.ml
index a7c5a005f0..eee0c79065 100644
--- a/tools/cmt2annot.ml
+++ b/tools/cmt2annot.ml
@@ -87,8 +87,10 @@ let iterator 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_function (_, f, _)
- | Texp_match (_, f, _)
| Texp_try (_, f) ->
bind_cases f
| _ -> ()
@@ -154,7 +156,7 @@ let gen_annot target_filename filename
match target_filename with
| None -> Some (filename ^ ".annot")
| Some "-" -> None
- | Some filename -> target_filename
+ | Some _ -> target_filename
in
let iterator = iterator cmt_use_summaries in
match cmt_annots with
@@ -187,7 +189,7 @@ let gen_ml target_filename filename cmt =
let target_filename = match target_filename with
None -> Some (filename ^ ext)
| Some "-" -> None
- | Some filename -> target_filename
+ | Some _ -> target_filename
in
let oc = match target_filename with
None -> None
diff --git a/tools/depend.ml b/tools/depend.ml
index 01d3349c30..b6556c5c93 100644
--- a/tools/depend.ml
+++ b/tools/depend.ml
@@ -26,12 +26,12 @@ let rec addmodule bv lid =
Lident s ->
if not (StringSet.mem s bv)
then free_structure_names := StringSet.add s !free_structure_names
- | Ldot(l, s) -> addmodule bv l
+ | Ldot(l, _s) -> addmodule bv l
| Lapply(l1, l2) -> addmodule bv l1; addmodule bv l2
let add bv lid =
match lid.txt with
- Ldot(l, s) -> addmodule bv l
+ Ldot(l, _s) -> addmodule bv l
| _ -> ()
let addmodule bv lid = addmodule bv lid.txt
@@ -39,16 +39,16 @@ let addmodule bv lid = addmodule bv lid.txt
let rec add_type bv ty =
match ty.ptyp_desc with
Ptyp_any -> ()
- | Ptyp_var v -> ()
+ | Ptyp_var _ -> ()
| Ptyp_arrow(_, t1, t2) -> add_type bv t1; add_type bv t2
| Ptyp_tuple tl -> List.iter (add_type bv) tl
| Ptyp_constr(c, tl) -> add bv c; List.iter (add_type bv) tl
- | Ptyp_object (fl, _) -> List.iter (fun (_, t) -> add_type bv t) fl
+ | Ptyp_object (fl, _) -> List.iter (fun (_, _, t) -> add_type bv t) fl
| Ptyp_class(c, tl) -> add bv c; List.iter (add_type bv) tl
- | Ptyp_alias(t, s) -> add_type bv t
+ | Ptyp_alias(t, _) -> add_type bv t
| Ptyp_variant(fl, _, _) ->
List.iter
- (function Rtag(_,_,stl) -> List.iter (add_type bv) stl
+ (function Rtag(_,_,_,stl) -> List.iter (add_type bv) stl
| Rinherit sty -> add_type bv sty)
fl
| Ptyp_poly(_, t) -> add_type bv t
@@ -63,11 +63,12 @@ let add_opt add_fn bv = function
None -> ()
| Some x -> add_fn bv x
-let add_constructor_decl bv pcd =
- begin match pcd.pcd_args with
+let add_constructor_arguments bv = function
| Pcstr_tuple l -> List.iter (add_type bv) l
| Pcstr_record l -> List.iter (fun l -> add_type bv l.pld_type) l
- end;
+
+let add_constructor_decl bv pcd =
+ add_constructor_arguments bv pcd.pcd_args;
Misc.may (add_type bv) pcd.pcd_res
let add_type_declaration bv td =
@@ -80,9 +81,21 @@ let add_type_declaration bv td =
| Ptype_variant cstrs ->
List.iter (add_constructor_decl bv) cstrs
| Ptype_record lbls ->
- List.iter (fun pld -> add_type bv pld.pld_type) lbls in
+ List.iter (fun pld -> add_type bv pld.pld_type) lbls
+ | Ptype_open -> () in
add_tkind td.ptype_kind
+let add_extension_constructor bv ext =
+ match ext.pext_kind with
+ Pext_decl(args, rty) ->
+ add_constructor_arguments bv args;
+ Misc.may (add_type bv) rty
+ | Pext_rebind lid -> add bv lid
+
+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) ->
@@ -100,6 +113,7 @@ and add_class_type_field bv pctf =
| 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 _ -> ()
let add_class_description bv infos =
@@ -127,6 +141,7 @@ let rec add_pattern bv pat =
| Ppat_type li -> add bv li
| Ppat_lazy p -> add_pattern bv p
| Ppat_unpack id -> pattern_bv := StringSet.add id.txt !pattern_bv
+ | Ppat_exception p -> add_pattern bv p
| Ppat_extension _ -> ()
let add_pattern bv pat =
@@ -170,10 +185,10 @@ let rec add_expr bv exp =
| Pexp_constraint(e1, ty2) ->
add_expr bv e1;
add_type bv ty2
- | Pexp_send(e, m) -> add_expr bv e
+ | Pexp_send(e, _m) -> add_expr bv e
| Pexp_new li -> add bv li
- | Pexp_setinstvar(v, e) -> add_expr bv e
- | Pexp_override sel -> List.iter (fun (s, e) -> add_expr bv e) sel
+ | Pexp_setinstvar(_v, e) -> add_expr bv e
+ | Pexp_override sel -> List.iter (fun (_s, e) -> add_expr bv e) sel
| Pexp_letmodule(id, m, e) ->
add_module bv m; add_expr (StringSet.add id.txt bv) e
| Pexp_assert (e) -> add_expr bv e
@@ -231,8 +246,10 @@ and add_sig_item bv item =
add_type bv vd.pval_type; bv
| Psig_type dcls ->
List.iter (add_type_declaration bv) dcls; bv
- | Psig_exception pcd ->
- add_constructor_decl bv pcd; bv
+ | Psig_typext te ->
+ add_type_extension bv te; bv
+ | Psig_exception pext ->
+ add_extension_constructor bv pext; bv
| Psig_module pmd ->
add_modtype bv pmd.pmd_type; StringSet.add pmd.pmd_name.txt bv
| Psig_recmodule decls ->
@@ -288,10 +305,11 @@ and add_struct_item bv item =
add_type bv vd.pval_type; bv
| Pstr_type dcls ->
List.iter (add_type_declaration bv) dcls; bv
- | Pstr_exception pcd ->
- add_constructor_decl bv pcd; bv
- | Pstr_exn_rebind er ->
- add bv er.pexrb_lid; bv
+ | Pstr_typext te ->
+ add_type_extension bv te;
+ bv
+ | Pstr_exception pext ->
+ add_extension_constructor bv pext; bv
| Pstr_module x ->
add_module bv x.pmb_expr; StringSet.add x.pmb_name.txt bv
| Pstr_recmodule bindings ->
@@ -355,7 +373,7 @@ and add_class_field bv pcf =
| Pcf_method(_, _, Cfk_virtual ty) -> add_type bv ty
| Pcf_constraint(ty1, ty2) -> add_type bv ty1; add_type bv ty2
| Pcf_initializer e -> add_expr bv e
- | Pcf_extension _ -> ()
+ | Pcf_attribute _ | Pcf_extension _ -> ()
and add_class_declaration bv decl =
add_class_expr bv decl.pci_expr
diff --git a/tools/dumpobj.ml b/tools/dumpobj.ml
index f1255e9cd2..d95c210da4 100644
--- a/tools/dumpobj.ml
+++ b/tools/dumpobj.ml
@@ -481,8 +481,8 @@ let print_reloc (info, pos) =
(* Print a .cmo file *)
-let dump_obj filename ic =
- let buffer = Misc.input_bytes ic (String.length cmo_magic_number) in
+let dump_obj ic =
+ let buffer = really_input_string ic (String.length cmo_magic_number) in
if buffer <> cmo_magic_number then begin
prerr_endline "Not an object file"; exit 2
end;
@@ -502,7 +502,7 @@ let dump_obj filename ic =
(* Read the primitive table from an executable *)
let read_primitive_table ic len =
- let p = Misc.input_bytes ic len in
+ let p = really_input_string ic len in
let rec split beg cur =
if cur >= len then []
else if p.[cur] = '\000' then
@@ -557,7 +557,7 @@ let arg_fun filename =
begin try
objfile := false; dump_exe ic
with Bytesections.Bad_magic_number ->
- objfile := true; seek_in ic 0; dump_obj filename ic
+ objfile := true; seek_in ic 0; dump_obj ic
end;
close_in ic;
printf "## end of ocaml dump of %S\n%!" filename
diff --git a/tools/make-version-header.sh b/tools/make-version-header.sh
index b5e69be956..26c5c14280 100755
--- a/tools/make-version-header.sh
+++ b/tools/make-version-header.sh
@@ -13,9 +13,6 @@
# #
#########################################################################
-# For maximal compatibility with older versions, we Use "ocamlc -v"
-# instead of "ocamlc -vnum" or the VERSION file in .../lib/ocaml/.
-
# This script extracts the components from an OCaml version number
# and provides them as C defines:
# OCAML_VERSION_MAJOR: the major version number
@@ -26,7 +23,18 @@
# Note that additional-info is always absent in officially-released
# versions of OCaml.
-version="`ocamlc -v | sed -n -e 's/.*version //p'`"
+# usage:
+# make-version-header.sh [version-file]
+# The argument is the VERSION file from the OCaml sources.
+# If the argument is not given, the version number from "ocamlc -v" will
+# be used.
+
+case $# in
+ 0) version="`ocamlc -v | sed -n -e 's/.*version //p'`";;
+ 1) version="`sed -e 1q $1`";;
+ *) echo "usage: make-version-header.sh [version-file]" >&2
+ exit 2;;
+esac
major="`echo "$version" | sed -n -e '1s/^\([0-9]*\)\..*/\1/p'`"
minor="`echo "$version" | sed -n -e '1s/^[0-9]*\.\([0-9]*\).*/\1/p'`"
@@ -34,10 +42,12 @@ patchlvl="`echo "$version" | sed -n -e '1s/^[0-9]*\.[0-9]*\.\([0-9]*\).*/\1/p'`"
suffix="`echo "$version" | sed -n -e '1s/^[^+]*+\(.*\)/\1/p'`"
echo "#define OCAML_VERSION_MAJOR $major"
-echo "#define OCAML_VERSION_MINOR $minor"
+printf "#define OCAML_VERSION_MINOR %d\n" $minor
case $patchlvl in "") patchlvl=0;; esac
echo "#define OCAML_VERSION_PATCHLEVEL $patchlvl"
case "$suffix" in
"") echo "#undef OCAML_VERSION_ADDITIONAL";;
*) echo "#define OCAML_VERSION_ADDITIONAL \"$suffix\"";;
esac
+printf "#define OCAML_VERSION %d%02d%02d\n" $major $minor $patchlvl
+echo "#define OCAML_VERSION_STRING \"$version\""
diff --git a/tools/objinfo.ml b/tools/objinfo.ml
index 6f3ec75665..37a03b3427 100644
--- a/tools/objinfo.ml
+++ b/tools/objinfo.ml
@@ -31,11 +31,18 @@ let input_stringlist ic len =
else acc
in fold 0 0 []
in
- let sect = Misc.input_bytes ic len in
+ let sect = really_input_string ic len in
get_string_list sect len
-let print_name_crc (name, crc) =
- printf "\t%s\t%s\n" (Digest.to_hex crc) name
+let dummy_crc = String.make 32 '-'
+
+let print_name_crc (name, crco) =
+ let crc =
+ match crco with
+ None -> dummy_crc
+ | Some crc -> Digest.to_hex crc
+ in
+ printf "\t%s\t%s\n" crc name
let print_line name =
printf "\t%s\n" name
@@ -69,11 +76,28 @@ let print_cma_infos (lib : Cmo_format.library) =
printf "\n";
List.iter print_cmo_infos lib.lib_units
-let print_cmi_infos name sign crcs =
+let print_cmi_infos name crcs =
printf "Unit name: %s\n" name;
printf "Interfaces imported:\n";
List.iter print_name_crc crcs
+let print_cmt_infos cmt =
+ let open Cmt_format in
+ printf "Cmt unit name: %s\n" cmt.cmt_modname;
+ print_string "Cmt interfaces imported:\n";
+ List.iter print_name_crc cmt.cmt_imports;
+ printf "Source file: %s\n"
+ (match cmt.cmt_sourcefile with None -> "(none)" | Some f -> f);
+ printf "Compilation flags:";
+ Array.iter print_spaced_string cmt.cmt_args;
+ printf "\nLoad path:";
+ List.iter print_spaced_string cmt.cmt_loadpath;
+ printf "\n";
+ printf "cmt interface digest: %s\n"
+ (match cmt.cmt_interface_digest with
+ | None -> ""
+ | Some crc -> Digest.to_hex crc)
+
let print_general_infos name crc defines cmi cmx =
printf "Name: %s\n" name;
printf "CRC of implementation: %s\n" (Digest.to_hex crc);
@@ -143,7 +167,7 @@ let dump_byte ic =
| "CRCS" ->
p_section
"Imported units"
- (input_value ic : (string * Digest.t) list)
+ (input_value ic : (string * Digest.t option) list)
| "DLLS" ->
p_list
"Used DLLs"
@@ -189,7 +213,7 @@ let dump_obj filename =
printf "File %s\n" filename;
let ic = open_in_bin filename in
let len_magic_number = String.length cmo_magic_number in
- let magic_number = Misc.input_bytes ic len_magic_number in
+ let magic_number = really_input_string ic len_magic_number in
if magic_number = cmo_magic_number then begin
let cu_pos = input_binary_int ic in
seek_in ic cu_pos;
@@ -202,11 +226,19 @@ let dump_obj filename =
let toc = (input_value ic : library) in
close_in ic;
print_cma_infos toc
- end else if magic_number = cmi_magic_number then begin
- let cmi = Cmi_format.input_cmi ic in
+ end else if magic_number = cmi_magic_number ||
+ magic_number = cmt_magic_number then begin
close_in ic;
- print_cmi_infos cmi.Cmi_format.cmi_name cmi.Cmi_format.cmi_sign
- cmi.Cmi_format.cmi_crcs
+ let cmi, cmt = Cmt_format.read filename in
+ begin match cmi with
+ | None -> ()
+ | Some cmi ->
+ print_cmi_infos cmi.Cmi_format.cmi_name cmi.Cmi_format.cmi_crcs
+ end;
+ begin match cmt with
+ | None -> ()
+ | Some cmt -> print_cmt_infos cmt
+ end
end else if magic_number = cmx_magic_number then begin
let ui = (input_value ic : unit_infos) in
let crc = Digest.input ic in
@@ -219,7 +251,7 @@ let dump_obj filename =
end else begin
let pos_trailer = in_channel_length ic - len_magic_number in
let _ = seek_in ic pos_trailer in
- let _ = really_input ic magic_number 0 len_magic_number in
+ let magic_number = really_input_string ic len_magic_number in
if magic_number = Config.exec_magic_number then begin
dump_byte ic;
close_in ic
diff --git a/tools/ocamlcp.ml b/tools/ocamlcp.ml
index bca5ae63c5..75adcb82ef 100644
--- a/tools/ocamlcp.ml
+++ b/tools/ocamlcp.ml
@@ -54,6 +54,7 @@ module Options = Main_args.Make_bytecomp_options (struct
let _dllib = option_with_arg "-dllib"
let _dllpath = option_with_arg "-dllpath"
let _dtypes = option "-dtypes"
+ let _for_pack = option_with_arg "-for-pack"
let _g = option "-g"
let _i = option "-i"
let _I s = option_with_arg "-I" s
@@ -64,25 +65,28 @@ module Options = Main_args.Make_bytecomp_options (struct
let _labels = option "-labels"
let _linkall = option "-linkall"
let _make_runtime = option "-make-runtime"
+ let _no_alias_deps = option "-no-alias-deps"
let _no_app_funct = option "-no-app-funct"
let _noassert = option "-noassert"
let _nolabels = option "-nolabels"
let _noautolink = option "-noautolink"
let _nostdlib = option "-nostdlib"
let _o s = option_with_arg "-o" s
+ let _open s = option_with_arg "-open" s
let _output_obj = option "-output-obj"
let _pack = option "-pack"
- let _pp s = incompatible "-pp"
- let _ppx s = incompatible "-ppx"
+ let _pp _s = incompatible "-pp"
+ let _ppx _s = incompatible "-ppx"
let _principal = option "-principal"
let _rectypes = option "-rectypes"
let _runtime_variant s = option_with_arg "-runtime-variant" s
+ let _safe_string = option "-safe-string"
let _short_paths = option "-short-paths"
let _strict_sequence = option "-strict-sequence"
- let _trans_mod = option "-trans-mod"
let _thread () = option "-thread" ()
let _vmthread () = option "-vmthread" ()
let _unsafe = option "-unsafe"
+ let _unsafe_string = option "-unsafe-string"
let _use_prims s = option_with_arg "-use-prims" s
let _use_runtime s = option_with_arg "-use-runtime" s
let _v = option "-v"
diff --git a/tools/ocamldep.ml b/tools/ocamldep.ml
index 735a5f97b5..59fecc412c 100644
--- a/tools/ocamldep.ml
+++ b/tools/ocamldep.ml
@@ -18,7 +18,6 @@ let ppf = Format.err_formatter
type file_kind = ML | MLI;;
-let include_dirs = ref []
let load_path = ref ([] : (string * string array) list)
let ml_synonyms = ref [".ml"]
let mli_synonyms = ref [".mli"]
@@ -35,11 +34,7 @@ let files = ref []
let fix_slash s =
if Sys.os_type = "Unix" then s else begin
- let r = String.copy s in
- for i = 0 to String.length r - 1 do
- if r.[i] = '\\' then r.[i] <- '/'
- done;
- r
+ String.map (function '\\' -> '/' | c -> c) s
end
(* Since we reinitialize load_path after reading OCAMLCOMP,
@@ -160,20 +155,20 @@ let print_filename s =
else count n (i+1)
in
let spaces = count 0 0 in
- let result = String.create (String.length s + spaces) in
+ let result = Bytes.create (String.length s + spaces) in
let rec loop i j =
if i >= String.length s then ()
else if s.[i] = ' ' then begin
- result.[j] <- '\\';
- result.[j+1] <- ' ';
+ Bytes.set result j '\\';
+ Bytes.set result (j+1) ' ';
loop (i+1) (j+2);
end else begin
- result.[j] <- s.[i];
+ Bytes.set result j s.[i];
loop (i+1) (j+1);
end
in
loop 0 0;
- print_string result;
+ print_bytes result;
end
;;
@@ -205,7 +200,7 @@ let print_raw_dependencies source_file deps =
(* Process one file *)
-let report_err source_file exn =
+let report_err exn =
error_occurred := true;
match exn with
| Sys_error msg ->
@@ -217,13 +212,15 @@ let report_err source_file exn =
Location.report_error err
| None -> raise x
+let tool_name = "ocamldep"
+
let read_parse_and_extract parse_function extract_function magic source_file =
Depend.free_structure_names := Depend.StringSet.empty;
try
let input_file = Pparse.preprocess source_file in
begin try
let ast =
- Pparse.file Format.err_formatter input_file parse_function magic in
+ Pparse.file ~tool_name Format.err_formatter input_file parse_function magic in
extract_function Depend.StringSet.empty ast;
Pparse.remove_preprocessed input_file;
!Depend.free_structure_names
@@ -232,7 +229,7 @@ let read_parse_and_extract parse_function extract_function magic source_file =
raise x
end
with x ->
- report_err source_file x;
+ report_err x;
Depend.StringSet.empty
let ml_file_dependencies source_file =
@@ -288,7 +285,7 @@ let mli_file_dependencies source_file =
print_raw_dependencies source_file extracted_deps
end else begin
let basename = Filename.chop_extension source_file in
- let (byt_deps, opt_deps) =
+ let (byt_deps, _opt_deps) =
Depend.StringSet.fold (find_dependency MLI)
extracted_deps ([], []) in
print_dependencies [basename ^ ".cmi"] byt_deps
@@ -299,7 +296,7 @@ let file_dependencies_as kind source_file =
load_path := [];
List.iter add_to_load_path (
(!Compenv.last_include_dirs @
- !include_dirs @
+ !Clflags.include_dirs @
!Compenv.first_include_dirs
));
Location.input_name := source_file;
@@ -309,7 +306,7 @@ let file_dependencies_as kind source_file =
| ML -> ml_file_dependencies source_file
| MLI -> mli_file_dependencies source_file
end
- with x -> report_err source_file x
+ with x -> report_err x
let file_dependencies source_file =
if List.exists (Filename.check_suffix source_file) !ml_synonyms then
@@ -324,8 +321,9 @@ let sort_files_by_dependencies files =
(* Init Hashtbl with all defined modules *)
let files = List.map (fun (file, file_kind, deps) ->
- let modname = Filename.chop_extension (Filename.basename file) in
- modname.[0] <- Char.uppercase modname.[0];
+ let modname =
+ String.capitalize (Filename.chop_extension (Filename.basename file))
+ in
let key = (modname, file_kind) in
let new_deps = ref [] in
Hashtbl.add h key (file, new_deps);
@@ -414,7 +412,7 @@ let _ =
" Show absolute filenames in error messages";
"-all", Arg.Set all_dependencies,
" Generate dependencies on all files";
- "-I", Arg.String (fun s -> include_dirs := s :: !include_dirs),
+ "-I", Arg.String (fun s -> Clflags.include_dirs := s :: !Clflags.include_dirs),
"<dir> Add <dir> to the list of include directories";
"-impl", Arg.String (file_dependencies_as ML),
"<f> Process <f> as a .ml file";
diff --git a/tools/ocamlmklib.ml b/tools/ocamlmklib.ml
index 0ef86979b9..77ae57becb 100644
--- a/tools/ocamlmklib.ml
+++ b/tools/ocamlmklib.ml
@@ -215,10 +215,14 @@ let prepostfix pre name post =
let transl_path s =
match Sys.os_type with
| "Win32" ->
+ let s = Bytes.of_string s in
let rec aux i =
- if i = String.length s || s.[i] = ' ' then s
- else (if s.[i] = '/' then s.[i] <- '\\'; aux (i + 1))
- in aux 0
+ if i = Bytes.length s || Bytes.get s i = ' ' then s
+ else begin
+ if Bytes.get s i = '/' then Bytes.set s i '\\';
+ aux (i + 1)
+ end
+ in Bytes.to_string (aux 0)
| _ -> s
let build_libs () =
diff --git a/tools/ocamloptp.ml b/tools/ocamloptp.ml
index 6d730f2c3c..178f7c2d25 100644
--- a/tools/ocamloptp.ml
+++ b/tools/ocamloptp.ml
@@ -64,28 +64,32 @@ module Options = Main_args.Make_optcomp_options (struct
let _keep_locs = option "-keep-locs"
let _labels = option "-labels"
let _linkall = option "-linkall"
+ let _no_alias_deps = option "-no-alias-deps"
let _no_app_funct = option "-no-app-funct"
+ let _no_float_const_prop = option "-no-float-const-prop"
let _noassert = option "-noassert"
let _noautolink = option "-noautolink"
let _nodynlink = option "-nodynlink"
let _nolabels = option "-nolabels"
let _nostdlib = option "-nostdlib"
let _o s = option_with_arg "-o" s
+ let _open s = option_with_arg "-open" s
let _output_obj = option "-output-obj"
let _p = option "-p"
let _pack = option "-pack"
- let _pp s = incompatible "-pp"
- let _ppx s = incompatible "-ppx"
+ let _pp _s = incompatible "-pp"
+ let _ppx _s = incompatible "-ppx"
let _principal = option "-principal"
let _rectypes = option "-rectypes"
let _runtime_variant s = option_with_arg "-runtime-variant" s
let _S = option "-S"
+ let _safe_string = option "-safe-string"
let _short_paths = option "-short-paths"
let _strict_sequence = option "-strict-sequence"
let _shared = option "-shared"
let _thread = option "-thread"
- let _trans_mod = option "-trans-mod"
let _unsafe = option "-unsafe"
+ let _unsafe_string = option "-unsafe-string"
let _v = option "-v"
let _version = option "-version"
let _vnum = option "-vnum"
@@ -105,6 +109,7 @@ module Options = Main_args.Make_optcomp_options (struct
let _dcmm = option "-dcmm"
let _dsel = option "-dsel"
let _dcombine = option "-dcombine"
+ let _dcse = option "-dcse"
let _dlive = option "-dlive"
let _dspill = option "-dspill"
let _dsplit = option "-dsplit"
diff --git a/tools/ocamlprof.ml b/tools/ocamlprof.ml
index 1fde3fe495..9c2bb489dd 100644
--- a/tools/ocamlprof.ml
+++ b/tools/ocamlprof.ml
@@ -35,7 +35,7 @@ and inchan = ref stdin
and outchan = ref stdout
(* To copy source fragments *)
-let copy_buffer = String.create 256
+let copy_buffer = Bytes.create 256
let copy_chars_unix nchars =
let n = ref nchars in
@@ -173,8 +173,8 @@ and rewrite_exp iflag sexp =
and rw_exp iflag sexp =
match sexp.pexp_desc with
- Pexp_ident lid -> ()
- | Pexp_constant cst -> ()
+ Pexp_ident _lid -> ()
+ | Pexp_constant _cst -> ()
| Pexp_let(_, spat_sexp_list, sbody) ->
rewrite_patexp_list iflag spat_sexp_list;
@@ -314,7 +314,7 @@ and rewrite_annotate_exp_list l =
l
and rewrite_function iflag = function
- | [{pc_lhs=spat; pc_guard=None;
+ | [{pc_lhs=_; pc_guard=None;
pc_rhs={pexp_desc = (Pexp_function _|Pexp_fun _)} as sexp}] ->
rewrite_exp iflag sexp
| l -> rewrite_funmatching l
@@ -344,6 +344,7 @@ and rewrite_class_field iflag cf =
| Pcf_method (_, _, Cfk_virtual _)
| Pcf_val (_, _, Cfk_virtual _)
| Pcf_constraint _ -> ()
+ | Pcf_attribute _ -> ()
| Pcf_extension _ -> ()
and rewrite_class_expr iflag cexpr =
@@ -370,11 +371,11 @@ and rewrite_class_declaration iflag cl =
and rewrite_mod iflag smod =
match smod.pmod_desc with
- Pmod_ident lid -> ()
+ Pmod_ident _ -> ()
| Pmod_structure sstr -> List.iter (rewrite_str_item iflag) sstr
- | Pmod_functor(param, smty, sbody) -> rewrite_mod iflag sbody
+ | Pmod_functor(_param, _smty, sbody) -> rewrite_mod iflag sbody
| Pmod_apply(smod1, smod2) -> rewrite_mod iflag smod1; rewrite_mod iflag smod2
- | Pmod_constraint(smod, smty) -> rewrite_mod iflag smod
+ | Pmod_constraint(smod, _smty) -> rewrite_mod iflag smod
| Pmod_unpack(sexp) -> rewrite_exp iflag sexp
| Pmod_extension _ -> ()
diff --git a/tools/profiling.ml b/tools/profiling.ml
index 5dae8e4614..49a84108ec 100644
--- a/tools/profiling.ml
+++ b/tools/profiling.ml
@@ -37,7 +37,7 @@ let dump_counters () =
then raise Bad_profile)
!counters prevl;
List.iter2
- (fun (curname, (_,curcount)) (prevname, (_,prevcount)) ->
+ (fun (_curname, (_,curcount)) (_prevname, (_,prevcount)) ->
for i = 0 to Array.length curcount - 1 do
curcount.(i) <- curcount.(i) + prevcount.(i)
done)
diff --git a/tools/read_cmt.ml b/tools/read_cmt.ml
index 0ff9f3df77..eacba02a50 100644
--- a/tools/read_cmt.ml
+++ b/tools/read_cmt.ml
@@ -27,6 +27,8 @@ let arg_list = [
let arg_usage =
"read_cmt [OPTIONS] FILE.cmt : read FILE.cmt and print related information"
+let dummy_crc = String.make 32 '-'
+
let print_info cmt =
let open Cmt_format in
Printf.printf "module name: %s\n" cmt.cmt_modname;
@@ -60,8 +62,13 @@ let print_info cmt =
| Some digest ->
Printf.printf "interface digest: %s\n" (Digest.to_hex digest);
end;
- List.iter (fun (name, digest) ->
- Printf.printf "import: %s %s\n" name (Digest.to_hex digest);
+ List.iter (fun (name, crco) ->
+ let crc =
+ match crco with
+ None -> dummy_crc
+ | Some crc -> Digest.to_hex crc
+ in
+ Printf.printf "import: %s %s\n" name crc;
) (List.sort compare cmt.cmt_imports);
Printf.printf "%!";
()
diff --git a/tools/tast_iter.ml b/tools/tast_iter.ml
index f640ccaf79..be5b854419 100644
--- a/tools/tast_iter.ml
+++ b/tools/tast_iter.ml
@@ -17,21 +17,14 @@ let opt f = function None -> () | Some x -> f x
let structure sub str =
List.iter (sub # structure_item) str.str_items
-let constructor_decl sub cd =
- begin match cd.cd_args with
- | Cstr_tuple l -> List.iter (sub # core_type) l
- | Cstr_record l -> List.iter (fun ld -> sub # core_type ld.ld_type) l
- end;
- opt (sub # core_type) cd.cd_res
-
let structure_item sub x =
match x.str_desc with
| Tstr_eval (exp, _attrs) -> sub # expression exp
| Tstr_value (rec_flag, list) -> sub # bindings (rec_flag, list)
| Tstr_primitive v -> sub # value_description v
| Tstr_type list -> List.iter (sub # type_declaration) list
- | Tstr_exception decl -> constructor_decl sub decl
- | Tstr_exn_rebind _ -> ()
+ | Tstr_typext te -> sub # type_extension te
+ | Tstr_exception ext -> sub # extension_constructor ext
| Tstr_module mb -> sub # module_binding mb
| Tstr_recmodule list -> List.iter (sub # module_binding) list
| Tstr_modtype mtd -> opt (sub # module_type) mtd.mtd_type
@@ -46,6 +39,17 @@ let structure_item sub x =
let value_description sub x =
sub # core_type x.val_desc
+let constructor_args sub = function
+ | Cstr_tuple l -> List.iter (sub # core_type) l
+ | Cstr_record l -> List.iter (fun ld -> sub # core_type ld.ld_type) l
+
+let constructor_decl sub cd =
+ constructor_args sub cd.cd_args;
+ opt (sub # core_type) cd.cd_res
+
+let label_decl sub ld =
+ sub # core_type ld.ld_type
+
let type_declaration sub decl =
List.iter
(fun (ct1, ct2, _loc) -> sub # core_type ct1; sub # core_type ct2)
@@ -55,10 +59,21 @@ let type_declaration sub decl =
| Ttype_variant list ->
List.iter (constructor_decl sub) list
| Ttype_record list ->
- List.iter (fun ld -> sub # core_type ld.ld_type) list
+ List.iter (label_decl sub) list
+ | Ttype_open -> ()
end;
opt (sub # core_type) decl.typ_manifest
+let type_extension sub te =
+ List.iter (sub # extension_constructor) te.tyext_constructors
+
+let extension_constructor sub ext =
+ match ext.ext_kind with
+ Text_decl(ctl, cto) ->
+ constructor_args sub ctl;
+ opt (sub # core_type) cto
+ | Text_rebind _ -> ()
+
let pattern sub pat =
let extra = function
| Tpat_type _
@@ -101,9 +116,10 @@ let expression sub exp =
| Texp_apply (exp, list) ->
sub # expression exp;
List.iter (fun (_, expo, _) -> opt (sub # expression) expo) list
- | Texp_match (exp, cases, _) ->
+ | Texp_match (exp, cases, exn_cases, _) ->
sub # expression exp;
- sub # cases cases
+ sub # cases cases;
+ sub # cases exn_cases
| Texp_try (exp, cases) ->
sub # expression exp;
sub # cases cases
@@ -169,8 +185,10 @@ let signature_item sub item =
sub # value_description v
| Tsig_type list ->
List.iter (sub # type_declaration) list
- | Tsig_exception decl ->
- constructor_decl sub decl
+ | Tsig_typext te ->
+ sub # type_extension te
+ | Tsig_exception ext ->
+ sub # extension_constructor ext
| Tsig_module md ->
sub # module_type md.md_type
| Tsig_recmodule list ->
@@ -277,6 +295,7 @@ let class_type_field sub ctf =
| Tctf_constraint (ct1, ct2) ->
sub # core_type ct1;
sub # core_type ct2
+ | Tctf_attribute _ -> ()
let core_type sub ct =
match ct.ctyp_desc with
@@ -289,7 +308,7 @@ let core_type sub ct =
| Ttyp_constr (_path, _, list) ->
List.iter (sub # core_type) list
| Ttyp_object (list, _o) ->
- List.iter (fun (_, t) -> sub # core_type t) list
+ List.iter (fun (_, _, t) -> sub # core_type t) list
| Ttyp_class (_path, _, list) ->
List.iter (sub # core_type) list
| Ttyp_alias (ct, _s) ->
@@ -305,7 +324,7 @@ let class_structure sub cs =
let row_field sub rf =
match rf with
- | Ttag (_label, _bool, list) -> List.iter (sub # core_type) list
+ | Ttag (_label, _attrs, _bool, list) -> List.iter (sub # core_type) list
| Tinherit ct -> sub # core_type ct
let class_field sub cf =
@@ -325,6 +344,7 @@ let class_field sub cf =
sub # expression exp
| Tcf_initializer exp ->
sub # expression exp
+ | Tcf_attribute _ -> ()
let bindings sub (_rec_flag, list) =
List.iter (sub # binding) list
@@ -356,6 +376,7 @@ class iter = object(this)
method class_type_field = class_type_field this
method core_type = core_type this
method expression = expression this
+ method extension_constructor = extension_constructor this
method module_binding = module_binding this
method module_expr = module_expr this
method module_type = module_type this
@@ -367,6 +388,7 @@ class iter = object(this)
method structure = structure this
method structure_item = structure_item this
method type_declaration = type_declaration this
+ method type_extension = type_extension this
method value_description = value_description this
method with_constraint = with_constraint this
end
diff --git a/tools/tast_iter.mli b/tools/tast_iter.mli
index f80609566b..1d81afa568 100644
--- a/tools/tast_iter.mli
+++ b/tools/tast_iter.mli
@@ -28,6 +28,7 @@ class iter: object
method class_type_field: class_type_field -> unit
method core_type: core_type -> unit
method expression: expression -> unit
+ method extension_constructor: extension_constructor -> unit
method module_binding: module_binding -> unit
method module_expr: module_expr -> unit
method module_type: module_type -> unit
@@ -39,6 +40,7 @@ class iter: object
method structure: structure -> unit
method structure_item: structure_item -> unit
method type_declaration: type_declaration -> unit
+ method type_extension: type_extension -> unit
method value_description: value_description -> unit
method with_constraint: with_constraint -> unit
end
@@ -63,6 +65,7 @@ val class_type_declaration: iter -> class_type_declaration -> unit
val class_type_field: iter -> class_type_field -> unit
val core_type: iter -> core_type -> unit
val expression: iter -> expression -> unit
+val extension_constructor: iter -> extension_constructor -> unit
val module_binding: iter -> module_binding -> unit
val module_expr: iter -> module_expr -> unit
val module_type: iter -> module_type -> unit
@@ -74,5 +77,6 @@ val signature_item: iter -> signature_item -> unit
val structure: iter -> structure -> unit
val structure_item: iter -> structure_item -> unit
val type_declaration: iter -> type_declaration -> unit
+val type_extension: iter -> type_extension -> unit
val value_description: iter -> value_description -> unit
val with_constraint: iter -> with_constraint -> unit
diff --git a/tools/untypeast.ml b/tools/untypeast.ml
index c6c7b3bc9e..b59443c595 100644
--- a/tools/untypeast.ml
+++ b/tools/untypeast.ml
@@ -53,10 +53,10 @@ and untype_structure_item item =
Pstr_primitive (untype_value_description vd)
| Tstr_type list ->
Pstr_type (List.map untype_type_declaration list)
- | Tstr_exception decl ->
- Pstr_exception (untype_constructor_declaration decl)
- | Tstr_exn_rebind er ->
- Pstr_exn_rebind (untype_exception_rebind er)
+ | Tstr_typext tyext ->
+ Pstr_typext (untype_type_extension tyext)
+ | Tstr_exception ext ->
+ Pstr_exception (untype_extension_constructor ext)
| Tstr_module mb ->
Pstr_module (untype_module_binding mb)
| Tstr_recmodule list ->
@@ -71,26 +71,15 @@ and untype_structure_item item =
popen_loc = od.open_loc;
}
| Tstr_class list ->
- Pstr_class (List.map (fun (ci, _, _) ->
- { pci_virt = ci.ci_virt;
- pci_params = ci.ci_params;
- pci_name = ci.ci_id_name;
- pci_expr = untype_class_expr ci.ci_expr;
- pci_loc = ci.ci_loc;
- pci_attributes = ci.ci_attributes;
- }
- ) list)
+ Pstr_class
+ (List.map
+ (fun (ci, _, _) -> untype_class_declaration ci)
+ list)
| Tstr_class_type list ->
- Pstr_class_type (List.map (fun (_id, _name, ct) ->
- {
- pci_virt = ct.ci_virt;
- pci_params = ct.ci_params;
- pci_name = ct.ci_id_name;
- pci_expr = untype_class_type ct.ci_expr;
- pci_loc = ct.ci_loc;
- pci_attributes = ct.ci_attributes;
- }
- ) list)
+ Pstr_class_type
+ (List.map
+ (fun (_id, _name, ct) -> untype_class_type_declaration ct)
+ list)
| Tstr_include incl ->
Pstr_include {pincl_mod = untype_module_expr incl.incl_mod;
pincl_attributes = incl.incl_attributes;
@@ -121,7 +110,7 @@ and untype_module_binding mb =
and untype_type_declaration decl =
{
ptype_name = decl.typ_name;
- ptype_params = decl.typ_params;
+ ptype_params = List.map untype_type_parameter decl.typ_params;
ptype_cstrs = List.map (fun (ct1, ct2, loc) ->
(untype_core_type ct1,
untype_core_type ct2, loc)
@@ -132,6 +121,7 @@ and untype_type_declaration decl =
Ptype_variant (List.map untype_constructor_declaration list)
| Ttype_record list ->
Ptype_record (List.map untype_label_declaration list)
+ | Ttype_open -> Ptype_open
);
ptype_private = decl.typ_private;
ptype_manifest = option untype_core_type decl.typ_manifest;
@@ -139,33 +129,51 @@ and untype_type_declaration decl =
ptype_loc = decl.typ_loc;
}
+and untype_type_parameter (ct, v) = (untype_core_type ct, v)
+
+and untype_constructor_arguments = function
+ | Cstr_tuple l -> Pcstr_tuple (List.map untype_core_type l)
+ | Cstr_record l -> Pcstr_record (List.map untype_label_declaration l)
+
+and untype_constructor_declaration cd =
+ {
+ pcd_name = cd.cd_name;
+ pcd_args = untype_constructor_arguments cd.cd_args;
+ pcd_res = option untype_core_type cd.cd_res;
+ pcd_loc = cd.cd_loc;
+ pcd_attributes = cd.cd_attributes;
+ }
+
and untype_label_declaration ld =
{
pld_name=ld.ld_name;
pld_mutable=ld.ld_mutable;
pld_type=untype_core_type ld.ld_type;
pld_loc=ld.ld_loc;
- pld_attributes=ld.ld_attributes;
+ pld_attributes=ld.ld_attributes
}
-and untype_constructor_declaration cd =
+and untype_type_extension tyext =
{
- pcd_name = cd.cd_name;
- pcd_args = begin match cd.cd_args with
- | Cstr_tuple l -> Pcstr_tuple (List.map untype_core_type l)
- | Cstr_record l -> Pcstr_record (List.map untype_label_declaration l)
- end;
- pcd_res = option untype_core_type cd.cd_res;
- pcd_loc = cd.cd_loc;
- pcd_attributes = cd.cd_attributes;
+ ptyext_path = tyext.tyext_txt;
+ ptyext_params = List.map untype_type_parameter tyext.tyext_params;
+ ptyext_constructors =
+ List.map untype_extension_constructor tyext.tyext_constructors;
+ ptyext_private = tyext.tyext_private;
+ ptyext_attributes = tyext.tyext_attributes;
}
-and untype_exception_rebind er =
+and untype_extension_constructor ext =
{
- pexrb_name = er.exrb_name;
- pexrb_lid = er.exrb_txt;
- pexrb_attributes = er.exrb_attributes;
- pexrb_loc = er.exrb_loc;
+ pext_name = ext.ext_name;
+ pext_kind = (match ext.ext_kind with
+ Text_decl (args, ret) ->
+ Pext_decl (untype_constructor_arguments args,
+ option untype_core_type ret)
+ | Text_rebind (_p, lid) -> Pext_rebind lid
+ );
+ pext_loc = ext.ext_loc;
+ pext_attributes = ext.ext_attributes;
}
and untype_pattern pat =
@@ -270,8 +278,18 @@ and untype_expression exp =
None -> list
| Some exp -> (label, untype_expression exp) :: list
) list [])
- | Texp_match (exp, cases, _) ->
- Pexp_match (untype_expression exp, untype_cases cases)
+ | Texp_match (exp, cases, exn_cases, _) ->
+ let merged_cases = untype_cases cases
+ @ List.map
+ (fun c ->
+ let uc = untype_case 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 (untype_expression exp, merged_cases)
| Texp_try (exp, cases) ->
Pexp_try (untype_expression exp, untype_cases cases)
| Texp_tuple list ->
@@ -352,8 +370,10 @@ and untype_signature_item item =
Psig_value (untype_value_description v)
| Tsig_type list ->
Psig_type (List.map untype_type_declaration list)
- | Tsig_exception decl ->
- Psig_exception (untype_constructor_declaration decl)
+ | Tsig_typext tyext ->
+ Psig_typext (untype_type_extension tyext)
+ | Tsig_exception ext ->
+ Psig_exception (untype_extension_constructor ext)
| Tsig_module md ->
Psig_module {pmd_name = md.md_name;
pmd_type = untype_module_type md.md_type;
@@ -389,10 +409,20 @@ and untype_signature_item item =
psig_loc = item.sig_loc;
}
+and untype_class_declaration cd =
+ {
+ pci_virt = cd.ci_virt;
+ pci_params = List.map untype_type_parameter cd.ci_params;
+ pci_name = cd.ci_id_name;
+ pci_expr = untype_class_expr cd.ci_expr;
+ pci_loc = cd.ci_loc;
+ pci_attributes = cd.ci_attributes;
+ }
+
and untype_class_description cd =
{
pci_virt = cd.ci_virt;
- pci_params = cd.ci_params;
+ pci_params = List.map untype_type_parameter cd.ci_params;
pci_name = cd.ci_id_name;
pci_expr = untype_class_type cd.ci_expr;
pci_loc = cd.ci_loc;
@@ -402,7 +432,7 @@ and untype_class_description cd =
and untype_class_type_declaration cd =
{
pci_virt = cd.ci_virt;
- pci_params = cd.ci_params;
+ pci_params = List.map untype_type_parameter cd.ci_params;
pci_name = cd.ci_id_name;
pci_expr = untype_class_type cd.ci_expr;
pci_loc = cd.ci_loc;
@@ -523,6 +553,7 @@ and untype_class_type_field ctf =
Pctf_method (s, priv, virt, untype_core_type ct)
| Tctf_constraint (ct1, ct2) ->
Pctf_constraint (untype_core_type ct1, untype_core_type ct2)
+ | Tctf_attribute x -> Pctf_attribute x
in
{
pctf_desc = desc;
@@ -541,7 +572,8 @@ and untype_core_type ct =
Ptyp_constr (lid,
List.map untype_core_type list)
| Ttyp_object (list, o) ->
- Ptyp_object (List.map (fun (s, t) -> (s, untype_core_type t)) list, o)
+ Ptyp_object
+ (List.map (fun (s, a, t) -> (s, a, untype_core_type t)) list, o)
| Ttyp_class (_path, lid, list) ->
Ptyp_class (lid, List.map untype_core_type list)
| Ttyp_alias (ct, s) ->
@@ -560,8 +592,8 @@ and untype_class_structure cs =
and untype_row_field rf =
match rf with
- Ttag (label, bool, list) ->
- Rtag (label, bool, List.map untype_core_type list)
+ Ttag (label, attrs, bool, list) ->
+ Rtag (label, attrs, bool, List.map untype_core_type list)
| Tinherit ct -> Rinherit (untype_core_type ct)
and untype_class_field cf =
@@ -579,5 +611,6 @@ and untype_class_field cf =
| Tcf_method (lab, priv, Tcfk_concrete (o, exp)) ->
Pcf_method (lab, priv, Cfk_concrete (o, untype_expression exp))
| Tcf_initializer exp -> Pcf_initializer (untype_expression exp)
+ | Tcf_attribute x -> Pcf_attribute x
in
{ pcf_desc = desc; pcf_loc = cf.cf_loc; pcf_attributes = cf.cf_attributes }
diff --git a/toplevel/expunge.ml b/toplevel/expunge.ml
index fa6fd7ca5a..a893c60ddc 100644
--- a/toplevel/expunge.ml
+++ b/toplevel/expunge.ml
@@ -65,7 +65,7 @@ let main () =
let global_map = (input_value ic : Symtable.global_map) in
output_value oc (expunge_map global_map)
| "CRCS" ->
- let crcs = (input_value ic : (string * Digest.t) list) in
+ let crcs = (input_value ic : (string * Digest.t option) list) in
output_value oc (expunge_crcs crcs)
| _ ->
copy_file_chunk ic oc len
diff --git a/toplevel/genprintval.ml b/toplevel/genprintval.ml
index 2ebff822fa..6519d3941c 100644
--- a/toplevel/genprintval.ml
+++ b/toplevel/genprintval.ml
@@ -50,6 +50,15 @@ module type S =
Env.t -> t -> type_expr -> Outcometree.out_value
end
+module ObjTbl = Hashtbl.Make(struct
+ type t = Obj.t
+ let equal = (==)
+ let hash x =
+ try
+ Hashtbl.hash x
+ with exn -> 0
+ end)
+
module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
type t = O.t
@@ -173,6 +182,24 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
let printer_steps = ref max_steps in
+ let nested_values = ObjTbl.create 8 in
+ let nest_gen err f depth obj ty =
+ let repr = Obj.repr obj in
+ if not (Obj.is_block repr) then
+ f depth obj ty
+ else
+ if ObjTbl.mem nested_values repr then
+ err
+ else begin
+ ObjTbl.add nested_values repr ();
+ let ret = f depth obj ty in
+ ObjTbl.remove nested_values repr;
+ ret
+ end
+ in
+
+ let nest f = nest_gen (Oval_stuff "<cycle>") f in
+
let rec tree_of_val depth obj ty =
decr printer_steps;
if !printer_steps < 0 || depth < 0 then Oval_ellipsis
@@ -187,25 +214,26 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
Oval_stuff "<fun>"
| Ttuple(ty_list) ->
Oval_tuple (tree_of_val_list 0 depth obj ty_list)
- | Tconstr(path, [], _) when Path.same path Predef.path_exn ->
- tree_of_exception depth obj
| Tconstr(path, [ty_arg], _)
when Path.same path Predef.path_list ->
if O.is_block obj then
match check_depth depth obj ty with
Some x -> x
| None ->
- let rec tree_of_conses tree_list obj =
+ let rec tree_of_conses tree_list depth obj ty_arg =
if !printer_steps < 0 || depth < 0 then
Oval_ellipsis :: tree_list
else if O.is_block obj then
let tree =
- tree_of_val (depth - 1) (O.field obj 0) ty_arg in
+ nest tree_of_val (depth - 1) (O.field obj 0) ty_arg
+ in
let next_obj = O.field obj 1 in
- tree_of_conses (tree :: tree_list) next_obj
+ nest_gen (Oval_stuff "<cycle>" :: tree :: tree_list)
+ (tree_of_conses (tree :: tree_list))
+ depth next_obj ty_arg
else tree_list
in
- Oval_list (List.rev (tree_of_conses [] obj))
+ Oval_list (List.rev (tree_of_conses [] depth obj ty_arg))
else
Oval_list []
| Tconstr(path, [ty_arg], _)
@@ -220,7 +248,8 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
Oval_ellipsis :: tree_list
else if i < length then
let tree =
- tree_of_val (depth - 1) (O.field obj i) ty_arg in
+ nest tree_of_val (depth - 1) (O.field obj i) ty_arg
+ in
tree_of_items (tree :: tree_list) (i + 1)
else tree_list
in
@@ -230,11 +259,13 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
| Tconstr (path, [ty_arg], _)
when Path.same path Predef.path_lazy_t ->
if Lazy.lazy_is_val (O.obj obj)
- then let v = tree_of_val depth (Lazy.force (O.obj obj)) ty_arg in
- Oval_constr (Oide_ident "lazy", [v])
+ then let v =
+ nest tree_of_val depth (Lazy.force (O.obj obj)) ty_arg
+ in
+ Oval_constr (Oide_ident "lazy", [v])
else Oval_stuff "<lazy>"
- | Tconstr(path, ty_list, _) ->
- begin try
+ | Tconstr(path, ty_list, _) -> begin
+ try
let decl = Env.find_type path env in
match decl with
| {type_kind = Type_abstract; type_manifest = None} ->
@@ -288,13 +319,15 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
| None ->
let pos =
match rep with
- | Record_exception _ -> 1
+ | Record_extension _ -> 1
| _ -> 0
in
tree_of_record_fields depth
env path decl.type_params ty_list
lbl_list pos
end
+ | {type_kind = Type_open} ->
+ tree_of_extension path depth obj
with
Not_found -> (* raised by Env.find_type *)
Oval_stuff "<abstr>"
@@ -311,8 +344,9 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
match Btype.row_field_repr f with
| Rpresent(Some ty) | Reither(_,[ty],_,_) ->
let args =
- tree_of_val (depth - 1) (O.field obj 1) ty in
- Oval_variant (l, Some args)
+ nest tree_of_val (depth - 1) (O.field obj 1) ty
+ in
+ Oval_variant (l, Some args)
| _ -> find fields
else find fields
| [] -> Oval_stuff "<variant>" in
@@ -356,7 +390,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
if pos = 0 then tree_of_label env path name
else Oide_ident name
and v =
- tree_of_val (depth - 1) (O.field obj pos)
+ nest tree_of_val (depth - 1) (O.field obj pos)
ty_arg
in
(lid, v) :: tree_of_fields (pos + 1) remainder
@@ -367,7 +401,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
let rec tree_list i = function
| [] -> []
| ty :: ty_list ->
- let tree = tree_of_val (depth - 1) (O.field obj i) ty in
+ let tree = nest tree_of_val (depth - 1) (O.field obj i) ty in
tree :: tree_list (i + 1) ty_list in
tree_list start ty_list
@@ -384,7 +418,7 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
in
Oval_constr (lid, args)
- and tree_of_exception depth bucket =
+ and tree_of_extension type_path depth bucket =
let slot =
if O.tag bucket <> 0 then bucket
else O.field bucket 0
@@ -397,7 +431,9 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
let cstr = Env.lookup_constructor lid env in
let path =
match cstr.cstr_tag with
- Cstr_exception (p, _) -> p | _ -> raise Not_found in
+ Cstr_extension(p, _) -> p
+ | _ -> raise Not_found
+ 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 *)
@@ -409,8 +445,11 @@ module Make(O : OBJ)(EVP : EVALPATH with type valu = O.t) = struct
with Not_found | EVP.Error ->
match check_depth depth bucket ty with
Some x -> x
- | None -> outval_of_untyped_exception bucket
+ | None when Path.same type_path Predef.path_exn->
+ outval_of_untyped_exception bucket
+ | None ->
+ Oval_stuff "<extension>"
- in tree_of_val max_depth obj ty
+ in nest tree_of_val max_depth obj ty
end
diff --git a/toplevel/opttoploop.ml b/toplevel/opttoploop.ml
index 5bac897810..9e9e3d7447 100644
--- a/toplevel/opttoploop.ml
+++ b/toplevel/opttoploop.ml
@@ -92,6 +92,7 @@ let print_out_value = Oprint.out_value
let print_out_type = Oprint.out_type
let print_out_class_type = Oprint.out_class_type
let print_out_module_type = Oprint.out_module_type
+let print_out_type_extension = Oprint.out_type_extension
let print_out_sig_item = Oprint.out_sig_item
let print_out_signature = Oprint.out_signature
let print_out_phrase = Oprint.out_phrase
@@ -171,8 +172,8 @@ let rec pr_item env = function
| Sig_type(id, decl, rs) :: rem ->
let tree = Printtyp.tree_of_type_declaration id decl rs in
Some (tree, None, rem)
- | Sig_exception(id, decl) :: rem ->
- let tree = Printtyp.tree_of_exception_declaration id decl in
+ | Sig_typext(id, ext, es) :: rem ->
+ let tree = Printtyp.tree_of_extension_constructor id ext es in
Some (tree, None, rem)
| Sig_module(id, mty, rs) :: rem ->
let tree = Printtyp.tree_of_module id mty rs in
diff --git a/toplevel/opttoploop.mli b/toplevel/opttoploop.mli
index 3be9a51ea8..2236255818 100644
--- a/toplevel/opttoploop.mli
+++ b/toplevel/opttoploop.mli
@@ -84,6 +84,8 @@ val print_out_class_type :
(formatter -> Outcometree.out_class_type -> unit) ref
val print_out_module_type :
(formatter -> Outcometree.out_module_type -> unit) ref
+val print_out_type_extension :
+ (formatter -> Outcometree.out_type_extension -> unit) ref
val print_out_sig_item :
(formatter -> Outcometree.out_sig_item -> unit) ref
val print_out_signature :
diff --git a/toplevel/opttopmain.ml b/toplevel/opttopmain.ml
index 3e15c1988d..941c3ec26b 100644
--- a/toplevel/opttopmain.ml
+++ b/toplevel/opttopmain.ml
@@ -69,6 +69,7 @@ module Options = Main_args.Make_opttop_options (struct
let _init s = init_file := Some s
let _inline n = inline_threshold := n * 8
let _labels = clear classic
+ let _no_alias_deps = set transparent_modules
let _no_app_funct = clear applicative_functors
let _noassert = set noassert
let _nolabels = set classic
diff --git a/toplevel/topdirs.ml b/toplevel/topdirs.ml
index 873e795850..5fdaa2cb50 100644
--- a/toplevel/topdirs.ml
+++ b/toplevel/topdirs.ml
@@ -61,7 +61,12 @@ exception Load_failed
let check_consistency ppf filename cu =
try
List.iter
- (fun (name, crc) -> Consistbl.check Env.crc_units name crc filename)
+ (fun (name, crco) ->
+ Env.imported_units := name :: !Env.imported_units;
+ match crco with
+ None -> ()
+ | Some crc->
+ Consistbl.check Env.crc_units name crc filename)
cu.cu_imports
with Consistbl.Inconsistency(name, user, auth) ->
fprintf ppf "@[<hv 0>The files %s@ and %s@ \
@@ -75,7 +80,7 @@ let load_compunit ic filename ppf compunit =
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;
- String.unsafe_set code compunit.cu_codesize (Char.chr Opcodes.opRETURN);
+ Bytes.unsafe_set code compunit.cu_codesize (Char.chr Opcodes.opRETURN);
String.unsafe_blit "\000\000\000\001\000\000\000" 0
code (compunit.cu_codesize + 1) 7;
let initial_symtable = Symtable.current_state() in
@@ -110,7 +115,7 @@ let rec load_file recursive ppf name =
and really_load_file recursive ppf name filename ic =
let ic = open_in_bin filename in
- let buffer = Misc.input_bytes ic (String.length Config.cmo_magic_number) in
+ let buffer = really_input_string ic (String.length Config.cmo_magic_number) in
try
if buffer = Config.cmo_magic_number then begin
let compunit_pos = input_binary_int ic in (* Go to descriptor *)
@@ -340,70 +345,108 @@ let trim_signature = function
sg)
| mty -> mty
-let dir_show ppf args =
- let open Parsetree in
- let id lid =
- let s = match lid with
- Longident.Lident s -> s
+let show_prim to_sig ppf lid =
+ let env = !Toploop.toplevel_env in
+ let loc = Location.none in
+ try
+ let s =
+ match lid with
+ | Longident.Lident s -> s
| Longident.Ldot (_,s) -> s
| Longident.Lapply _ ->
fprintf ppf "Invalid path %a@." Printtyp.longident lid;
raise Exit
in
- Ident.create_persistent s
- in
- let env = !Toploop.toplevel_env in
- try
- let loc = Location.none in
- let item =
- match args with
- | [ Pdir_keyword "val"; Pdir_ident lid ] ->
- let id = id lid in
- let path, desc = Typetexp.find_value env loc lid in
- Sig_value (id, desc)
- | [ Pdir_keyword "type"; Pdir_ident lid ] ->
- let id = id lid in
- let path, desc = Typetexp.find_type env loc lid in
- Sig_type (id, desc, Trec_not)
- | [ Pdir_keyword "exception"; Pdir_ident lid ] ->
- let id = id lid in
- let desc = Typetexp.find_constructor env loc lid in
- begin match desc.cstr_tag with
- | Cstr_constant _ | Cstr_block _ ->
- fprintf ppf "@[This constructor is not an exception.@]@.";
- raise Exit
- | Cstr_exception _ ->
- Sig_exception (id, {exn_args=Cstr_tuple desc.cstr_args;
- exn_loc=desc.cstr_loc;
- exn_attributes=desc.cstr_attributes;
- })
- end
- | [ Pdir_keyword "module"; Pdir_ident lid ] ->
- let id = id lid in
- let path = Typetexp.find_module env loc lid in
- let md = Env.find_module path env in
- Sig_module (id, {md with md_type = trim_signature md.md_type},
- Trec_not)
- | [ Pdir_keyword "module"; Pdir_keyword "type"; Pdir_ident lid ] ->
- let id = id lid in
- let path, desc = Typetexp.find_modtype env loc lid in
- Sig_modtype (id, desc)
- | [ Pdir_keyword "class"; Pdir_ident lid ] ->
- let id = id lid in
- let path, desc = Typetexp.find_class env loc lid in
- Sig_class (id, desc, Trec_not)
- | [ Pdir_keyword "class"; Pdir_keyword "type"; Pdir_ident lid ] ->
- let id = id lid in
- let path, desc = Typetexp.find_class_type env loc lid in
- Sig_class_type (id, desc, Trec_not)
- | _ -> fprintf ppf "@[Bad usage for #show@]@."; raise Exit
- in
- fprintf ppf "@[%a@]@." Printtyp.signature [item]
+ let id = Ident.create_persistent s in
+ let sg = to_sig env loc id lid in
+ fprintf ppf "@[%a@]@." Printtyp.signature sg
with
| Not_found ->
fprintf ppf "@[Unknown element.@]@."
- | Exit ->
- ()
+ | Exit -> ()
+
+let all_show_funs = ref []
+
+let reg_show_prim name to_sig =
+ all_show_funs := to_sig :: !all_show_funs;
+ Hashtbl.add directive_table name (Directive_ident (show_prim to_sig std_out))
+
+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) ]
+ )
+
+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) ]
+ )
+
+let () =
+ reg_show_prim "show_exception"
+ (fun env loc id lid ->
+ let desc = Typetexp.find_constructor env loc lid in
+ if not (Ctype.equal env true [desc.cstr_res] [Predef.type_exn]) then
+ raise Not_found;
+ let ret_type =
+ if desc.cstr_generalized then Some Predef.type_exn
+ else None
+ in
+ let ext =
+ { ext_type_path = Predef.path_exn;
+ ext_type_params = [];
+ ext_args = Cstr_tuple desc.cstr_args;
+ ext_ret_type = ret_type;
+ ext_private = Asttypes.Public;
+ Types.ext_loc = desc.cstr_loc;
+ Types.ext_attributes = desc.cstr_attributes; }
+ in
+ [Sig_typext (id, ext, Text_exception)]
+ )
+
+let () =
+ reg_show_prim "show_module"
+ (fun env loc id lid ->
+ let path, md = Typetexp.find_module env loc lid in
+ [ Sig_module (id, {md with md_type = trim_signature md.md_type},
+ Trec_not) ]
+ )
+
+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) ]
+ )
+
+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) ]
+ )
+
+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) ]
+ )
+
+
+let show env loc id lid =
+ let sg =
+ List.fold_left
+ (fun sg f -> try (f env loc id lid) @ sg with _ -> sg)
+ [] !all_show_funs
+ in
+ if sg = [] then raise Not_found else sg
+
+let () =
+ Hashtbl.add directive_table "show" (Directive_ident (show_prim show std_out))
let _ =
Hashtbl.add directive_table "trace" (Directive_ident (dir_trace std_out));
@@ -429,13 +472,13 @@ let _ =
Hashtbl.add directive_table "rectypes"
(Directive_none(fun () -> Clflags.recursive_types := true));
+ Hashtbl.add directive_table "ppx"
+ (Directive_string(fun s -> Clflags.all_ppx := s :: !Clflags.all_ppx));
+
Hashtbl.add directive_table "warnings"
(Directive_string (parse_warnings std_out false));
Hashtbl.add directive_table "warn_error"
(Directive_string (parse_warnings std_out true));
- Hashtbl.add directive_table "show"
- (Directive_generic (dir_show std_out));
-
()
diff --git a/toplevel/toploop.ml b/toplevel/toploop.ml
index 83b8224371..a7311d7b41 100644
--- a/toplevel/toploop.ml
+++ b/toplevel/toploop.ml
@@ -28,21 +28,21 @@ type directive_fun =
| Directive_int of (int -> unit)
| Directive_ident of (Longident.t -> unit)
| Directive_bool of (bool -> unit)
- | Directive_generic of (Parsetree.directive_argument list -> unit)
(* The table of toplevel value bindings and its accessors *)
-let toplevel_value_bindings =
- (Hashtbl.create 37 : (string, Obj.t) Hashtbl.t)
+module StringMap = Map.Make(String)
+
+let toplevel_value_bindings : Obj.t StringMap.t ref = ref StringMap.empty
let getvalue name =
try
- Hashtbl.find toplevel_value_bindings name
+ StringMap.find name !toplevel_value_bindings
with Not_found ->
fatal_error (name ^ " unbound at toplevel")
let setvalue name v =
- Hashtbl.replace toplevel_value_bindings name v
+ toplevel_value_bindings := StringMap.add name v !toplevel_value_bindings
(* Return the value referred to by a path *)
@@ -53,7 +53,7 @@ let rec eval_path = function
else begin
let name = Translmod.toplevel_name id in
try
- Hashtbl.find toplevel_value_bindings name
+ StringMap.find name !toplevel_value_bindings
with Not_found ->
raise (Symtable.Error(Symtable.Undefined_global name))
end
@@ -83,6 +83,7 @@ let print_out_value = Oprint.out_value
let print_out_type = Oprint.out_type
let print_out_class_type = Oprint.out_class_type
let print_out_module_type = Oprint.out_module_type
+let print_out_type_extension = Oprint.out_type_extension
let print_out_sig_item = Oprint.out_sig_item
let print_out_signature = Oprint.out_signature
let print_out_phrase = Oprint.out_phrase
@@ -150,6 +151,7 @@ let load_lambda ppf lam =
Symtable.patch_object code reloc;
Symtable.check_global_initialized reloc;
Symtable.update_global_table();
+ let initial_bindings = !toplevel_value_bindings in
try
may_trace := true;
let retval = (Meta.reify_bytecode code code_size) () in
@@ -165,6 +167,7 @@ let load_lambda ppf lam =
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
@@ -245,20 +248,27 @@ let execute_phrase print_outcome ppf phr =
toplevel_env := oldenv; raise x
end
| Ptop_dir(dir_name, dir_arg) ->
- try
- match (Hashtbl.find directive_table dir_name, dir_arg) with
- | (Directive_none f, []) -> f (); true
- | (Directive_string f, [Pdir_string s]) -> f s; true
- | (Directive_int f, [Pdir_int n]) -> f n; true
- | (Directive_ident f, [Pdir_ident lid]) -> f lid; true
- | (Directive_bool f, [Pdir_bool b]) -> f b; true
- | (Directive_generic f, l) -> f l; true
- | (_, _) ->
- fprintf ppf "Wrong type of argument for directive `%s'.@." dir_name;
- false
- with Not_found ->
- fprintf ppf "Unknown directive `%s'.@." dir_name;
- false
+ let d =
+ try Some (Hashtbl.find directive_table dir_name)
+ with Not_found -> None
+ in
+ begin match d with
+ | None ->
+ 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 -> f n; true
+ | Directive_ident f, Pdir_ident lid -> f lid; true
+ | Directive_bool f, Pdir_bool b -> f b; true
+ | _ ->
+ fprintf ppf "Wrong type of argument for directive `%s'.@."
+ dir_name;
+ false
+ end
+
(* Temporary assignment to a reference *)
@@ -281,7 +291,7 @@ let phrase ppf phr =
let phr =
match phr with
| Ptop_def str ->
- Ptop_def (Pparse.apply_rewriters ast_impl_magic_number str)
+ Ptop_def (Pparse.apply_rewriters ~tool_name:"ocaml" ast_impl_magic_number str)
| phr -> phr
in
if !Clflags.dump_parsetree then Printast.top_phrase ppf phr;
@@ -341,7 +351,7 @@ let read_input_default prompt buffer len =
while true do
if !i >= len then raise Exit;
let c = input_char Pervasives.stdin in
- buffer.[!i] <- c;
+ Bytes.set buffer !i c;
incr i;
if c = '\n' then raise Exit;
done;
@@ -382,8 +392,12 @@ let _ =
let crc_intfs = Symtable.init_toplevel() in
Compmisc.init_path false;
List.iter
- (fun (name, crc) ->
- Consistbl.set Env.crc_units name crc Sys.executable_name)
+ (fun (name, crco) ->
+ Env.imported_units := name :: !Env.imported_units;
+ match crco with
+ None -> ()
+ | Some crc->
+ Consistbl.set Env.crc_units name crc Sys.executable_name)
crc_intfs
let load_ocamlinit ppf =
diff --git a/toplevel/toploop.mli b/toplevel/toploop.mli
index b364a088e7..5f0b86e261 100644
--- a/toplevel/toploop.mli
+++ b/toplevel/toploop.mli
@@ -39,7 +39,6 @@ type directive_fun =
| Directive_int of (int -> unit)
| Directive_ident of (Longident.t -> unit)
| Directive_bool of (bool -> unit)
- | Directive_generic of (Parsetree.directive_argument list -> unit)
val directive_table : (string, directive_fun) Hashtbl.t
(* Table of known directives, with their execution function *)
@@ -93,6 +92,8 @@ val print_out_class_type :
(formatter -> Outcometree.out_class_type -> unit) ref
val print_out_module_type :
(formatter -> Outcometree.out_module_type -> unit) ref
+val print_out_type_extension :
+ (formatter -> Outcometree.out_type_extension -> unit) ref
val print_out_sig_item :
(formatter -> Outcometree.out_sig_item -> unit) ref
val print_out_signature :
@@ -102,7 +103,7 @@ val print_out_phrase :
(* Hooks for external line editor *)
-val read_interactive_input : (string -> string -> int -> int * bool) ref
+val read_interactive_input : (string -> bytes -> int -> int * bool) ref
(* Hooks for initialization *)
diff --git a/toplevel/topmain.ml b/toplevel/topmain.ml
index 0f3ac66f9d..045be0b75c 100644
--- a/toplevel/topmain.ml
+++ b/toplevel/topmain.ml
@@ -67,20 +67,23 @@ module Options = Main_args.Make_bytetop_options (struct
let _init s = init_file := Some s
let _noinit = set noinit
let _labels = clear classic
+ let _no_alias_deps = set transparent_modules
let _no_app_funct = clear applicative_functors
let _noassert = set noassert
let _nolabels = set classic
let _noprompt = set noprompt
let _nopromptcont = set nopromptcont
let _nostdlib = set no_std_include
+ let _open s = open_modules := s :: !open_modules
let _ppx s = first_ppx := s :: !first_ppx
let _principal = set principal
let _rectypes = set recursive_types
+ let _safe_string = clear unsafe_string
let _short_paths = clear real_paths
let _stdin () = file_argument ""
let _strict_sequence = set strict_sequence
- let _trans_mod = set transparent_modules
let _unsafe = set fast
+ let _unsafe_string = set unsafe_string
let _version () = print_version ()
let _vnum () = print_version_num ()
let _w s = Warnings.parse_options false s
diff --git a/typing/btype.ml b/typing/btype.ml
index 730aa7c72e..6d1d8cdcd2 100644
--- a/typing/btype.ml
+++ b/typing/btype.ml
@@ -241,7 +241,7 @@ type type_iterators =
it_signature_item: type_iterators -> signature_item -> unit;
it_value_description: type_iterators -> value_description -> unit;
it_type_declaration: type_iterators -> type_declaration -> unit;
- it_exception_declaration: type_iterators -> exception_declaration -> unit;
+ it_extension_constructor: type_iterators -> extension_constructor -> unit;
it_module_declaration: type_iterators -> module_declaration -> unit;
it_modtype_declaration: type_iterators -> modtype_declaration -> unit;
it_class_declaration: type_iterators -> class_declaration -> unit;
@@ -253,20 +253,28 @@ type type_iterators =
it_type_expr: type_iterators -> type_expr -> unit;
it_path: Path.t -> unit; }
+let iter_type_expr_cstr_args f = function
+ | Cstr_tuple tl -> List.iter f tl
+ | Cstr_record (_, lbls) -> List.iter (fun d -> f d.ld_type) lbls
+
+let map_type_expr_cstr_args f = function
+ | Cstr_tuple tl -> Cstr_tuple (List.map f tl)
+ | Cstr_record (r, lbls) ->
+ Cstr_record (r, List.map (fun d -> {d with ld_type=f d.ld_type}) lbls)
+
let iter_type_expr_kind f = function
| Type_abstract -> ()
| Type_variant cstrs ->
List.iter
(fun cd ->
- begin match cd.cd_args with
- | Cstr_tuple tl -> List.iter f tl
- | Cstr_record (_, lbls) -> List.iter (fun d -> f d.ld_type) lbls
- end;
+ iter_type_expr_cstr_args f cd.cd_args;
Misc.may f cd.cd_res
)
cstrs
| Type_record(lbls, _) ->
List.iter (fun d -> f d.ld_type) lbls
+ | Type_open ->
+ ()
let type_iterators =
@@ -275,7 +283,7 @@ let type_iterators =
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_exception (_, ed) -> it.it_exception_declaration it ed
+ | 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
@@ -286,11 +294,11 @@ let type_iterators =
List.iter (it.it_type_expr it) td.type_params;
may (it.it_type_expr it) td.type_manifest;
it.it_type_kind it td.type_kind
- and it_exception_declaration it ed =
- match ed.exn_args with
- | Cstr_tuple tl -> List.iter (it.it_type_expr it) tl
- | Cstr_record (_, lbls) ->
- List.iter (fun d -> it.it_type_expr it d.ld_type) lbls
+ and it_extension_constructor it td =
+ it.it_path td.ext_type_path;
+ List.iter (it.it_type_expr it) td.ext_type_params;
+ iter_type_expr_cstr_args (it.it_type_expr it) td.ext_args;
+ may (it.it_type_expr it) td.ext_ret_type
and it_module_declaration it md =
it.it_module_type it md.md_type
and it_modtype_declaration it mtd =
@@ -342,7 +350,7 @@ let type_iterators =
{ it_path; it_type_expr = it_do_type_expr; it_do_type_expr;
it_type_kind; it_class_type; it_module_type;
it_signature; it_class_type_declaration; it_class_declaration;
- it_modtype_declaration; it_module_declaration; it_exception_declaration;
+ it_modtype_declaration; it_module_declaration; it_extension_constructor;
it_type_declaration; it_value_description; it_signature_item; }
let copy_row f fixed row keep more =
@@ -470,6 +478,11 @@ let unmark_iterators =
let unmark_type_decl decl =
unmark_iterators.it_type_declaration unmark_iterators decl
+let unmark_extension_constructor ext =
+ List.iter unmark_type ext.ext_type_params;
+ iter_type_expr_cstr_args unmark_type ext.ext_args;
+ Misc.may unmark_type ext.ext_ret_type
+
let unmark_class_signature sign =
unmark_type sign.csig_self;
Vars.iter (fun l (m, v, t) -> unmark_type t) sign.csig_vars
diff --git a/typing/btype.mli b/typing/btype.mli
index 35bc552a5d..bf7f9558a8 100644
--- a/typing/btype.mli
+++ b/typing/btype.mli
@@ -95,7 +95,7 @@ type type_iterators =
it_signature_item: type_iterators -> signature_item -> unit;
it_value_description: type_iterators -> value_description -> unit;
it_type_declaration: type_iterators -> type_declaration -> unit;
- it_exception_declaration: type_iterators -> exception_declaration -> unit;
+ it_extension_constructor: type_iterators -> extension_constructor -> unit;
it_module_declaration: type_iterators -> module_declaration -> unit;
it_modtype_declaration: type_iterators -> modtype_declaration -> unit;
it_class_declaration: type_iterators -> class_declaration -> unit;
@@ -139,6 +139,7 @@ val mark_type_params: type_expr -> unit
(* Mark the sons of a type node *)
val unmark_type: type_expr -> unit
val unmark_type_decl: type_declaration -> unit
+val unmark_extension_constructor: extension_constructor -> unit
val unmark_class_type: class_type -> unit
val unmark_class_signature: class_signature -> unit
(* Remove marks from a type *)
@@ -200,3 +201,7 @@ val log_type: type_expr -> unit
val print_raw: (Format.formatter -> type_expr -> unit) ref
val iter_type_expr_kind: (type_expr -> unit) -> (type_kind -> unit)
+val iter_type_expr_cstr_args: (type_expr -> unit) ->
+ (constructor_arguments -> unit)
+val map_type_expr_cstr_args: (type_expr -> type_expr) ->
+ (constructor_arguments -> constructor_arguments)
diff --git a/typing/cmi_format.ml b/typing/cmi_format.ml
index e5a8399fac..6f421fdcff 100644
--- a/typing/cmi_format.ml
+++ b/typing/cmi_format.ml
@@ -22,7 +22,7 @@ exception Error of error
type cmi_infos = {
cmi_name : string;
cmi_sign : Types.signature_item list;
- cmi_crcs : (string * Digest.t) list;
+ cmi_crcs : (string * Digest.t option) list;
cmi_flags : pers_flags list;
}
@@ -40,7 +40,9 @@ let input_cmi ic =
let read_cmi filename =
let ic = open_in_bin filename in
try
- let buffer = Misc.input_bytes ic (String.length Config.cmi_magic_number) in
+ let buffer =
+ really_input_string ic (String.length Config.cmi_magic_number)
+ in
if buffer <> Config.cmi_magic_number then begin
close_in ic;
let pre_len = String.length Config.cmi_magic_number - 3 in
@@ -70,7 +72,7 @@ let output_cmi filename oc cmi =
output_value oc (cmi.cmi_name, cmi.cmi_sign);
flush oc;
let crc = Digest.file filename in
- let crcs = (cmi.cmi_name, crc) :: cmi.cmi_crcs in
+ let crcs = (cmi.cmi_name, Some crc) :: cmi.cmi_crcs in
output_value oc crcs;
output_value oc cmi.cmi_flags;
crc
diff --git a/typing/cmi_format.mli b/typing/cmi_format.mli
index 2d6fdec6bb..32cec451fb 100644
--- a/typing/cmi_format.mli
+++ b/typing/cmi_format.mli
@@ -15,7 +15,7 @@ type pers_flags = Rectypes
type cmi_infos = {
cmi_name : string;
cmi_sign : Types.signature_item list;
- cmi_crcs : (string * Digest.t) list;
+ cmi_crcs : (string * Digest.t option) list;
cmi_flags : pers_flags list;
}
diff --git a/typing/cmt_format.ml b/typing/cmt_format.ml
index 29751de8f7..6cecb1b691 100644
--- a/typing/cmt_format.ml
+++ b/typing/cmt_format.ml
@@ -23,9 +23,7 @@ open Typedtree
let read_magic_number ic =
let len_magic_number = String.length Config.cmt_magic_number in
- let magic_number = String.create len_magic_number in
- really_input ic magic_number 0 len_magic_number;
- magic_number
+ really_input_string ic len_magic_number
type binary_annots =
| Packed of Types.signature * string list
@@ -56,7 +54,7 @@ type cmt_infos = {
cmt_loadpath : string list;
cmt_source_digest : Digest.t option;
cmt_initial_env : Env.t;
- cmt_imports : (string * Digest.t) list;
+ cmt_imports : (string * Digest.t option) list;
cmt_interface_digest : Digest.t option;
cmt_use_summaries : bool;
}
@@ -203,7 +201,7 @@ let record_value_dependency vd1 vd2 =
let save_cmt filename modname binary_annots sourcefile initial_env sg =
if !Clflags.binary_annotations && not !Clflags.print_types then begin
- let imports = Env.imported_units () in
+ let imports = Env.imports () in
let oc = open_out_bin filename in
let this_crc =
match sg with
diff --git a/typing/cmt_format.mli b/typing/cmt_format.mli
index ba264a314d..48fbc639e8 100644
--- a/typing/cmt_format.mli
+++ b/typing/cmt_format.mli
@@ -57,7 +57,7 @@ type cmt_infos = {
cmt_loadpath : string list;
cmt_source_digest : string option;
cmt_initial_env : Env.t;
- cmt_imports : (string * Digest.t) list;
+ cmt_imports : (string * Digest.t option) list;
cmt_interface_digest : Digest.t option;
cmt_use_summaries : bool;
}
diff --git a/typing/ctype.ml b/typing/ctype.ml
index 4989aa7ced..30b9ac3361 100644
--- a/typing/ctype.ml
+++ b/typing/ctype.ml
@@ -217,23 +217,38 @@ type unification_mode =
let umode = ref Expression
let generate_equations = ref false
+let assume_injective = ref false
-let set_mode mode ?(generate = (mode = Pattern)) f =
+let set_mode_expression f =
+ let old_unification_mode = !umode in
+ try
+ umode := Expression;
+ let ret = f () in
+ umode := old_unification_mode;
+ ret
+ with e ->
+ umode := old_unification_mode;
+ raise e
+
+let set_mode_pattern ~generate ~injective f =
let old_unification_mode = !umode
- and old_gen = !generate_equations in
+ and old_gen = !generate_equations
+ and old_inj = !assume_injective in
try
- umode := mode;
+ 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
-
(*** Checks for type definitions ***)
let in_current_module = function
@@ -242,12 +257,12 @@ let in_current_module = function
let in_pervasives p =
in_current_module p &&
- try ignore (Env.find_type p Env.initial); true
+ try ignore (Env.find_type p Env.initial_safe_string); true
with Not_found -> false
let is_datatype decl=
match decl.type_kind with
- Type_record _ | Type_variant _ -> true
+ Type_record _ | Type_variant _ | Type_open -> true
| Type_abstract -> false
@@ -555,6 +570,7 @@ let closed_type_decl decl =
v
| Type_record(r, rep) ->
List.iter (fun l -> closed_type l.ld_type) r
+ | Type_open -> ()
end;
begin match decl.type_manifest with
None -> ()
@@ -566,6 +582,19 @@ let closed_type_decl decl =
unmark_type_decl decl;
Some ty
+let closed_extension_constructor ext =
+ try
+ List.iter mark_type ext.ext_type_params;
+ begin match ext.ext_ret_type with
+ | Some _ -> ()
+ | None -> iter_type_expr_cstr_args closed_type ext.ext_args
+ end;
+ unmark_extension_constructor ext;
+ None
+ with Non_closed (ty, _) ->
+ unmark_extension_constructor ext;
+ Some ty
+
type closed_class_failure =
CC_Method of type_expr * bool * string * type_expr
| CC_Value of type_expr * bool * string * type_expr
@@ -1163,6 +1192,7 @@ let instance_parameterized_type_2 sch_args sch_lst sch =
let map_kind f = function
| Type_abstract -> Type_abstract
+ | Type_open -> Type_open
| Type_variant cl ->
Type_variant (
List.map
@@ -1680,7 +1710,9 @@ let occur env ty0 ty =
let occur_in env ty0 t =
try occur env ty0 t; false with Unify _ -> true
-(* checks that a local constraint is non recursive *)
+(* Check that a local constraint is well-founded *)
+(* PR#6405: not needed since we allow recursion and work on normalized types *)
+(*
let rec local_non_recursive_abbrev visited env p ty =
let ty = repr ty in
if not (List.memq ty !visited) then begin
@@ -1690,19 +1722,14 @@ let rec local_non_recursive_abbrev visited env p ty =
if Path.same p p' then raise Recursive_abbrev;
begin try
local_non_recursive_abbrev visited env p (try_expand_once_opt env ty)
- with Cannot_expand ->
- if !Clflags.recursive_types then () else
- iter_type_expr (local_non_recursive_abbrev visited env p) ty
+ with Cannot_expand -> ()
end
- | Tobject _ | Tvariant _ ->
- ()
- | _ ->
- if !Clflags.recursive_types then () else
- iter_type_expr (local_non_recursive_abbrev visited env p) ty
+ | _ -> ()
end
let local_non_recursive_abbrev env p =
local_non_recursive_abbrev (ref []) env p
+*)
(*****************************)
(* Polymorphic Unification *)
@@ -2116,10 +2143,6 @@ and mcomp_type_decl type_pairs env p1 p2 tl1 tl2 =
let decl = Env.find_type p1 env in
let decl' = Env.find_type p2 env in
if Path.same p1 p2 then begin
- (* Format.eprintf "@[%a@ %a@]@."
- !print_raw (newconstr p1 tl2) !print_raw (newconstr p2 tl2);
- if non_aliasable p1 decl then Format.eprintf "non_aliasable@."
- else Format.eprintf "aliasable@."; *)
let inj =
try List.map Variance.(mem Inj) (Env.find_type p1 env).type_variance
with Not_found -> List.map (fun _ -> false) tl1
@@ -2127,19 +2150,21 @@ and mcomp_type_decl type_pairs env p1 p2 tl1 tl2 =
List.iter2
(fun i (t1,t2) -> if i then mcomp type_pairs env t1 t2)
inj (List.combine tl1 tl2)
- end
- else match decl.type_kind, decl'.type_kind with
- | Type_record (lst,r), Type_record (lst',r') when r = r' ->
- mcomp_list type_pairs env tl1 tl2;
- mcomp_record_description type_pairs env lst lst'
- | Type_variant v1, Type_variant v2 ->
- mcomp_list type_pairs env tl1 tl2;
- mcomp_variant_description type_pairs env v1 v2
- | Type_variant _, Type_record _
- | Type_record _, Type_variant _ -> raise (Unify [])
- | _ ->
- if non_aliasable p1 decl && (non_aliasable p2 decl'||is_datatype decl')
- || is_datatype decl && non_aliasable p2 decl' then raise (Unify [])
+ end else if non_aliasable p1 decl && non_aliasable p2 decl' then raise (Unify [])
+ else
+ match decl.type_kind, decl'.type_kind with
+ | Type_record (lst,r), Type_record (lst',r') when r = r' ->
+ mcomp_list type_pairs env tl1 tl2;
+ mcomp_record_description type_pairs env lst lst'
+ | Type_variant v1, Type_variant v2 ->
+ mcomp_list type_pairs env tl1 tl2;
+ mcomp_variant_description type_pairs env v1 v2
+ | Type_open, Type_open ->
+ mcomp_list type_pairs env tl1 tl2
+ | Type_abstract, Type_abstract -> ()
+ | Type_abstract, _ when not (non_aliasable p1 decl)-> ()
+ | _, Type_abstract when not (non_aliasable p2 decl') -> ()
+ | _ -> raise (Unify [])
with Not_found -> ()
and mcomp_type_option type_pairs env t t' =
@@ -2427,11 +2452,13 @@ and unify3 env t1 t1' t2 t2' =
| (Ttuple tl1, Ttuple tl2) ->
unify_list env tl1 tl2
| (Tconstr (p1, tl1, _), Tconstr (p2, tl2, _)) when Path.same p1 p2 ->
- if !umode = Expression || not !generate_equations
- || in_current_module p1 (* || in_pervasives p1 *)
- || List.exists (expands_to_datatype !env) [t1'; t1; t2]
- (*try is_datatype (Env.find_type p1 !env) with Not_found -> false*)
- then
+ if !umode = Expression || not !generate_equations then
+ unify_list env tl1 tl2
+ else if !assume_injective then
+ set_mode_pattern ~generate:true ~injective:false
+ (fun () -> unify_list env tl1 tl2)
+ else if in_current_module p1 (* || in_pervasives p1 *)
+ || List.exists (expands_to_datatype !env) [t1'; t1; t2] then
unify_list env tl1 tl2
else
let inj =
@@ -2442,7 +2469,7 @@ and unify3 env t1 t1' t2 t2' =
List.iter2
(fun i (t1, t2) ->
if i then unify env t1 t2 else
- set_mode Pattern ~generate:false
+ set_mode_pattern ~generate:false ~injective:false
begin fun () ->
let snap = snapshot () in
try unify env t1 t2 with Unify _ ->
@@ -2462,12 +2489,12 @@ and unify3 env t1 t1' t2 t2' =
| (Tconstr ((Path.Pident p) as path,[],_), _)
when is_newtype !env path && !generate_equations ->
reify env t2';
- local_non_recursive_abbrev !env (Path.Pident p) t2';
+ (* local_non_recursive_abbrev !env (Path.Pident p) t2'; *)
add_gadt_equation env p t2'
| (_, Tconstr ((Path.Pident p) as path,[],_))
when is_newtype !env path && !generate_equations ->
reify env t1' ;
- local_non_recursive_abbrev !env (Path.Pident p) t1';
+ (* local_non_recursive_abbrev !env (Path.Pident p) t1'; *)
add_gadt_equation env p t1'
| (Tconstr (_,_,_), _) | (_, Tconstr (_,_,_)) when !umode = Pattern ->
reify env t1';
@@ -2749,7 +2776,7 @@ let unify_gadt ~newtype_level:lev (env:Env.t ref) ty1 ty2 =
try
univar_pairs := [];
newtype_level := Some lev;
- set_mode Pattern (fun () -> unify env ty1 ty2);
+ set_mode_pattern ~generate:true ~injective:true (fun () -> unify env ty1 ty2);
newtype_level := None;
TypePairs.clear unify_eq_set;
with e ->
@@ -4337,6 +4364,42 @@ let nondep_type_decl env mid id is_covariant decl =
clear_hash ();
raise Not_found
+(* Preserve sharing inside extension constructors. *)
+let nondep_extension_constructor env mid ext =
+ try
+ let type_path, type_params =
+ if Path.isfree mid ext.ext_type_path then
+ 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
+ match (repr ty').desc with
+ Tconstr(p, tl, _) -> p, tl
+ | _ -> raise Not_found
+ end
+ else
+ let type_params =
+ List.map (nondep_type_rec env mid) 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
+ clear_hash ();
+ { ext_type_path = type_path;
+ ext_type_params = type_params;
+ ext_args = args;
+ ext_ret_type = ret_type;
+ ext_private = ext.ext_private;
+ ext_attributes = ext.ext_attributes;
+ ext_loc = ext.ext_loc;
+ }
+ with Not_found ->
+ clear_hash ();
+ raise Not_found
+
+
(* Preserve sharing inside class types. *)
let nondep_class_signature env id sign =
{ csig_self = nondep_type_rec env id sign.csig_self;
diff --git a/typing/ctype.mli b/typing/ctype.mli
index 2af24c3681..b807fbd098 100644
--- a/typing/ctype.mli
+++ b/typing/ctype.mli
@@ -228,6 +228,10 @@ val nondep_type_decl:
Env.t -> Ident.t -> Ident.t -> bool -> type_declaration ->
type_declaration
(* Same for type declarations. *)
+val nondep_extension_constructor:
+ Env.t -> Ident.t -> extension_constructor ->
+ extension_constructor
+ (* Same for extension constructor *)
val nondep_class_declaration:
Env.t -> Ident.t -> class_declaration -> class_declaration
(* Same for class declarations. *)
@@ -245,6 +249,7 @@ val closed_schema: type_expr -> bool
val free_variables: ?env:Env.t -> type_expr -> type_expr list
(* If env present, then check for incomplete definitions too *)
val closed_type_decl: type_declaration -> type_expr option
+val closed_extension_constructor: extension_constructor -> type_expr option
type closed_class_failure =
CC_Method of type_expr * bool * string * type_expr
| CC_Value of type_expr * bool * string * type_expr
diff --git a/typing/datarepr.ml b/typing/datarepr.ml
index efc1fb20a2..ff6117bf41 100644
--- a/typing/datarepr.ml
+++ b/typing/datarepr.ml
@@ -164,28 +164,49 @@ let constructor_descrs ty_path decl manifest_decl cstrs =
let r = describe_constructors 0 0 cstrs in
r, !tdecls
-let exception_descr ?rebind path_exc decl =
- let type_manifest () = rebind in
+let extension_descr ?rebind path_ext ext =
+ let ty_res =
+ match ext.ext_ret_type with
+ Some type_ret -> type_ret
+ | None -> newgenconstr ext.ext_type_path ext.ext_type_params
+ in
+ (* TODO #5528: merge code below with constructor_descrs *)
+ let tyl =
+ match ext.ext_args with
+ | Cstr_tuple l -> l
+ | Cstr_record (_, l) -> List.map (fun l -> l.ld_type) l
+ in
+ let arg_vars_set, arg_vars = free_vars (newgenty (Ttuple tyl)) in
+ let existentials =
+ match ext.ext_ret_type with
+ | None -> []
+ | Some type_ret ->
+ let res_vars, _ = free_vars type_ret in
+ TypeSet.elements (TypeSet.diff arg_vars_set res_vars)
+ in
let cstr_args, cstr_inlined, tds =
- constructor_args path_exc type_manifest []
- (Record_exception path_exc)
- decl.exn_args
+ constructor_args path_ext (fun () -> rebind)
+ arg_vars
+ (Record_extension path_ext)
+ ext.ext_args
in
- { cstr_name = Path.last path_exc;
- cstr_res = Predef.type_exn;
- cstr_existentials = [];
- cstr_args;
- cstr_arity = List.length cstr_args;
- cstr_tag = Cstr_exception (path_exc, decl.exn_loc);
- cstr_consts = -1;
- cstr_nonconsts = -1;
- cstr_private = Public;
- cstr_normal = -1;
- cstr_generalized = false;
- cstr_loc = decl.exn_loc;
- cstr_attributes = decl.exn_attributes;
- cstr_inlined;
- }, tds
+ { cstr_name = Path.last path_ext;
+ cstr_res = ty_res;
+ cstr_existentials = existentials;
+ cstr_args;
+ cstr_arity = List.length cstr_args;
+ cstr_tag = Cstr_extension(path_ext, cstr_args = []);
+ cstr_consts = -1;
+ cstr_nonconsts = -1;
+ cstr_private = ext.ext_private;
+ cstr_normal = -1;
+ cstr_generalized = ext.ext_ret_type <> None;
+ cstr_loc = ext.ext_loc;
+ cstr_attributes = ext.ext_attributes;
+ cstr_inlined;
+ },
+ tds
+
let none = {desc = Ttuple []; level = -1; id = -1}
(* Clearly ill-formed type *)
diff --git a/typing/datarepr.mli b/typing/datarepr.mli
index fd5f07e0bf..6ae98fabaf 100644
--- a/typing/datarepr.mli
+++ b/typing/datarepr.mli
@@ -22,12 +22,11 @@ val constructor_descrs:
(Ident.t * constructor_description) list *
(Ident.t * Path.t * type_declaration) list
-val exception_descr:
+val extension_descr:
?rebind:Path.t ->
- Path.t -> exception_declaration ->
+ Path.t -> extension_constructor ->
constructor_description * (Ident.t * Path.t * type_declaration) list
-
val label_descrs:
type_expr -> label_declaration list ->
record_representation -> private_flag ->
diff --git a/typing/env.ml b/typing/env.ml
index 7d5959b6d4..448f2a881d 100644
--- a/typing/env.ml
+++ b/typing/env.ml
@@ -106,7 +106,7 @@ type summary =
Env_empty
| Env_value of summary * Ident.t * value_description
| Env_type of summary * Ident.t * type_declaration
- | Env_exception of summary * Ident.t * exception_declaration
+ | Env_extension of summary * Ident.t * extension_constructor
| Env_module of summary * Ident.t * module_declaration
| Env_modtype of summary * Ident.t * modtype_declaration
| Env_class of summary * Ident.t * class_declaration
@@ -242,13 +242,13 @@ let is_ident = function
let is_local (p, _) = is_ident p
-let is_local_exn = function
- | {cstr_tag = Cstr_exception (p, _)} -> is_ident p
+let is_local_ext = function
+ | {cstr_tag = Cstr_extension(p, _)} -> is_ident p
| _ -> false
let diff env1 env2 =
diff_keys is_local env1.values env2.values @
- diff_keys is_local_exn env1.constrs env2.constrs @
+ diff_keys is_local_ext env1.constrs env2.constrs @
diff_keys is_local env1.modules env2.modules @
diff_keys is_local env1.classes env2.classes
@@ -286,10 +286,9 @@ type pers_struct =
{ ps_name: string;
ps_sig: signature;
ps_comps: module_components;
- ps_crcs: (string * Digest.t) list;
+ ps_crcs: (string * Digest.t option) list;
ps_filename: string;
- ps_flags: pers_flags list;
- mutable ps_crcs_checked: bool }
+ ps_flags: pers_flags list }
let persistent_structures =
(Hashtbl.create 17 : (string, pers_struct option) Hashtbl.t)
@@ -297,14 +296,22 @@ let persistent_structures =
(* Consistency between persistent structures *)
let crc_units = Consistbl.create()
+let imported_units = ref ([] : string list)
+
+let clear_imports () =
+ Consistbl.clear crc_units;
+ imported_units := []
let check_consistency ps =
- if ps.ps_crcs_checked then () else
try
List.iter
- (fun (name, crc) -> Consistbl.check crc_units name crc ps.ps_filename)
- ps.ps_crcs;
- ps.ps_crcs_checked <- true
+ (fun (name, crco) ->
+ match crco with
+ None -> ()
+ | Some crc ->
+ imported_units := name :: !imported_units;
+ Consistbl.check crc_units name crc ps.ps_filename)
+ ps.ps_crcs
with Consistbl.Inconsistency(name, source, auth) ->
error (Inconsistent_import(name, auth, source))
@@ -325,12 +332,11 @@ let read_pers_struct modname filename =
ps_sig = sign;
ps_comps = comps;
ps_crcs = crcs;
- ps_crcs_checked = false;
ps_filename = filename;
ps_flags = flags } in
if ps.ps_name <> modname then
error (Illegal_renaming(modname, ps.ps_name, filename));
- if not !Clflags.transparent_modules then check_consistency ps;
+ imported_units := name :: !imported_units;
List.iter
(function Rectypes ->
if not !Clflags.recursive_types then
@@ -350,13 +356,13 @@ let find_pers_struct ?(check=true) name =
| Some None -> raise Not_found
| Some (Some sg) -> sg
| None ->
- let filename =
- try find_in_path_uncap !load_path (name ^ ".cmi")
- with Not_found ->
- Hashtbl.add persistent_structures name None;
- raise Not_found
- in
- read_pers_struct name filename
+ let filename =
+ try find_in_path_uncap !load_path (name ^ ".cmi")
+ with Not_found ->
+ Hashtbl.add persistent_structures name None;
+ raise Not_found
+ in
+ read_pers_struct name filename
in
if check then check_consistency ps;
ps
@@ -364,7 +370,7 @@ let find_pers_struct ?(check=true) name =
let reset_cache () =
current_unit := "";
Hashtbl.clear persistent_structures;
- Consistbl.clear crc_units;
+ clear_imports ();
Hashtbl.clear value_declarations;
Hashtbl.clear type_declarations;
Hashtbl.clear used_constructors;
@@ -615,7 +621,7 @@ let rec lookup_module_descr lid env =
end
| Lapply(l1, l2) ->
let (p1, desc1) = lookup_module_descr l1 env in
- let p2 = lookup_module l2 env in
+ let p2 = lookup_module true l2 env in
let {md_type=mty2} = find_module p2 env in
begin match EnvLazy.force !components_of_module_maker' desc1 with
Functor_comps f ->
@@ -625,7 +631,7 @@ let rec lookup_module_descr lid env =
raise Not_found
end
-and lookup_module lid env : Path.t =
+and lookup_module ~load lid env : Path.t =
match lid with
Lident s ->
begin try
@@ -639,7 +645,11 @@ and lookup_module lid env : Path.t =
p
with Not_found ->
if s = !current_unit then raise Not_found;
- ignore (find_pers_struct ~check:false s);
+ if !Clflags.transparent_modules && not load then
+ try ignore (find_pers_struct ~check:false s)
+ with Not_found ->
+ Location.prerr_warning Location.none (Warnings.No_cmi_file s)
+ else ignore (find_pers_struct s);
Pident(Ident.create_persistent s)
end
| Ldot(l, s) ->
@@ -653,7 +663,7 @@ and lookup_module lid env : Path.t =
end
| Lapply(l1, l2) ->
let (p1, desc1) = lookup_module_descr l1 env in
- let p2 = lookup_module l2 env in
+ let p2 = lookup_module true l2 env in
let {md_type=mty2} = find_module p2 env in
let p = Papply(p1, p2) in
begin match EnvLazy.force !components_of_module_maker' desc1 with
@@ -728,7 +738,7 @@ let has_local_constraints env = env.local_constraints
let cstr_shadow cstr1 cstr2 =
match cstr1.cstr_tag, cstr2.cstr_tag with
- Cstr_exception _, Cstr_exception _ -> true
+ | Cstr_extension _, Cstr_extension _ -> true
| _ -> false
let lbl_shadow lbl1 lbl2 = false
@@ -762,8 +772,9 @@ let mark_constructor_used usage name vd constr =
try Hashtbl.find used_constructors (name, vd.type_loc, constr) usage
with Not_found -> ()
-let mark_exception_used usage ed constr =
- try Hashtbl.find used_constructors ("exn", ed.exn_loc, constr) usage
+let mark_extension_used usage ext name =
+ let ty_name = Path.last ext.ext_type_path in
+ try Hashtbl.find used_constructors (ty_name, ext.ext_loc, name) usage
with Not_found -> ()
let set_value_used_callback name vd callback =
@@ -841,9 +852,11 @@ let lookup_all_constructors lid env =
let mark_constructor usage env name desc =
match desc.cstr_tag with
- | Cstr_exception (_, loc) ->
+ | Cstr_extension _ ->
begin
- try Hashtbl.find used_constructors ("exn", loc, name) usage
+ let ty_path = ty_path desc.cstr_res in
+ let ty_name = Path.last ty_path in
+ try Hashtbl.find used_constructors (ty_name, desc.cstr_loc, name) usage
with Not_found -> ()
end
| _ ->
@@ -1020,9 +1033,8 @@ let rec scrape_alias env ?path mty =
begin try
scrape_alias env (find_module path env).md_type ~path
with Not_found ->
- Location.prerr_warning Location.none
- (Warnings.Deprecated
- ("module " ^ Path.name path ^ " cannot be accessed"));
+ (*Location.prerr_warning Location.none
+ (Warnings.No_cmi_file (Path.name path));*)
mty
end
| mty, Some path ->
@@ -1045,7 +1057,7 @@ let constructors_of_type env ty_path decl =
| _ -> None
in
Datarepr.constructor_descrs ty_path decl manifest_decl cstrs
- | Type_record _ | Type_abstract -> [], []
+ | Type_record _ | Type_abstract | Type_open -> [], []
(* Compute label descriptions *)
@@ -1054,10 +1066,10 @@ let labels_of_type ty_path decl =
Type_record(labels, rep) ->
let rep =
match rep with
- | Record_exception (Pident id) ->
+ | Record_extension (Pident id) ->
begin match ty_path with
| Path.Pdot (path, _, pos) ->
- Record_exception (Path.Pdot (path, Ident.name id, pos))
+ Record_extension (Path.Pdot (path, Ident.name id, pos))
| Path.Pident _ ->
rep
| Path.Papply _ -> assert false
@@ -1067,7 +1079,7 @@ let labels_of_type ty_path decl =
Datarepr.label_descrs
(newgenty (Tconstr(ty_path, decl.type_params, ref Mnil)))
labels rep decl.type_private
- | Type_variant _ | Type_abstract -> []
+ | Type_variant _ | Type_abstract | Type_open -> []
(* Given a signature and a root path, prefix all idents in the signature
by the root path and build the corresponding substitution. *)
@@ -1085,9 +1097,9 @@ let rec prefix_idents root pos sub = function
let (pl, final_sub) =
prefix_idents root pos (Subst.add_type id p sub) rem in
(p::pl, final_sub)
- | Sig_exception(id, decl) :: rem ->
+ | Sig_typext(id, ext, _) :: rem ->
let p = Pdot(root, Ident.name id, pos) in
- let sub = Subst.add_prefixes root (Subst.sub_ids_exn decl) sub in
+ let sub = Subst.add_prefixes root (Subst.sub_ids_ext ext) sub in
let (pl, final_sub) = prefix_idents root (pos+1) sub rem in
(p::pl, final_sub)
| Sig_module(id, mty, _) :: rem ->
@@ -1118,8 +1130,8 @@ let subst_signature sub sg =
Sig_value (id, Subst.value_description sub decl)
| Sig_type(id, decl, x) ->
Sig_type(id, Subst.type_declaration sub decl, x)
- | Sig_exception(id, decl) ->
- Sig_exception (id, Subst.exception_declaration sub decl)
+ | Sig_typext(id, ext, es) ->
+ Sig_typext (id, Subst.extension_constructor sub ext, es)
| Sig_module(id, mty, x) ->
Sig_module(id, Subst.module_declaration sub mty,x)
| Sig_modtype(id, decl) ->
@@ -1210,17 +1222,16 @@ and components_of_module_maker (env, sub, path, mty) =
c.comp_labels <-
add_to_tbl descr.lbl_name (descr, nopos) c.comp_labels)
labels;
- env := store_type_infos None id path decl !env !env
- | Sig_exception(id, decl) ->
- let decl' = Subst.exception_declaration sub decl in
- let cstr, tdecls = Datarepr.exception_descr path decl' in
+ env := store_type_infos None id (Pident id) decl !env !env
+ | Sig_typext(id, ext, _) ->
+ let ext' = Subst.extension_constructor sub ext in
+ let descr, tdecls = Datarepr.extension_descr path ext' in
List.iter
(fun (id, path, td) ->
aux (Sig_type(id, td, Trec_next)) path;
) tdecls;
- let s = Ident.name id in
c.comp_constrs <-
- add_to_tbl s (cstr, !pos) c.comp_constrs;
+ add_to_tbl (Ident.name id) (descr, !pos) c.comp_constrs;
incr pos
| Sig_module(id, md, _) ->
let mty = md.md_type in
@@ -1230,13 +1241,13 @@ and components_of_module_maker (env, sub, path, mty) =
let comps = components_of_module !env sub path mty in
c.comp_components <-
Tbl.add (Ident.name id) (comps, !pos) c.comp_components;
- env := store_module None id path md !env !env;
+ env := store_module None id (Pident id) md !env !env;
incr pos
| Sig_modtype(id, decl) ->
let decl' = Subst.modtype_declaration sub decl in
c.comp_modtypes <-
Tbl.add (Ident.name id) (decl', nopos) c.comp_modtypes;
- env := store_modtype None id path decl !env !env
+ env := store_modtype None id (Pident id) decl !env !env
| Sig_class(id, decl, _) ->
let decl' = Subst.class_declaration sub decl in
c.comp_classes <-
@@ -1371,14 +1382,14 @@ and store_type_infos slot id path info env renv =
renv.types;
summary = Env_type(env.summary, id, info) }
-and store_exception ?rebind ~check slot id path decl env renv =
- let loc = decl.exn_loc in
+and store_extension ?rebind ~check slot id path ext env renv =
+ let loc = ext.ext_loc in
if check && not loc.Location.loc_ghost &&
- Warnings.is_active (Warnings.Unused_exception ("", false))
+ Warnings.is_active (Warnings.Unused_extension ("", false, false))
then begin
- let ty = "exn" in
- let c = Ident.name id in
- let k = (ty, loc, c) in
+ let ty = Path.last ext.ext_type_path in
+ let n = Ident.name id in
+ let k = (ty, loc, n) in
if not (Hashtbl.mem used_constructors k) then begin
let used = constructor_usages () in
Hashtbl.add used_constructors k (add_constructor_usage used);
@@ -1386,17 +1397,18 @@ and store_exception ?rebind ~check slot id path decl env renv =
(fun () ->
if not env.in_signature && not used.cu_positive then
Location.prerr_warning loc
- (Warnings.Unused_exception
- (c, used.cu_pattern)
+ (Warnings.Unused_extension
+ (n, used.cu_pattern, used.cu_privatize)
)
)
end;
+
end;
- let constr, tdecls = Datarepr.exception_descr ?rebind path decl in
+ let constr, tdecls = Datarepr.extension_descr ?rebind path ext in
let env = store_extra_tdecls slot tdecls env renv in
{ env with
constrs = EnvTbl.add "constructor" slot id constr env.constrs renv.constrs;
- summary = Env_exception(env.summary, id, decl) }
+ summary = Env_extension(env.summary, id, ext) }
and store_module slot id path md env renv =
{ env with
@@ -1459,8 +1471,8 @@ let add_value ?check id desc env =
let add_type ~check id info env =
store_type ~check None id (Pident id) info env env
-and add_exception ~check id decl env =
- store_exception ~check None id (Pident id) decl env env
+and add_extension ?rebind ~check id ext env =
+ store_extension ?rebind ~check None id (Pident id) ext env env
and add_module_declaration ?arg id md env =
let path =
@@ -1500,7 +1512,7 @@ let enter store_fun name data env =
let enter_value ?check = enter (store_value ?check)
and enter_type = enter (store_type ~check:true)
-and enter_exception ?rebind = enter (store_exception ?rebind ~check:true)
+and enter_extension ?rebind = enter (store_extension ?rebind ~check:true)
and enter_module_declaration ?arg name md env =
let id = Ident.create name in
(id, add_module_declaration ?arg id md env)
@@ -1519,7 +1531,7 @@ 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_exception(id, decl) -> add_exception ~check:false id decl env
+ | Sig_typext(id, ext, _) -> add_extension ~check:false id ext env
| Sig_module(id, md, _) -> add_module_declaration id md env
| Sig_modtype(id, decl) -> add_modtype id decl env
| Sig_class(id, decl, _) -> add_class id decl env
@@ -1547,8 +1559,8 @@ let open_signature slot root sg env0 =
store_value slot (Ident.hide id) p decl env env0
| Sig_type(id, decl, _) ->
store_type ~check:false slot (Ident.hide id) p decl env env0
- | Sig_exception(id, decl) ->
- store_exception ~check:false slot (Ident.hide id) p decl env env0
+ | Sig_typext(id, ext, _) ->
+ store_extension ~check:false slot (Ident.hide id) p ext env env0
| Sig_module(id, mty, _) ->
store_module slot (Ident.hide id) p mty env env0
| Sig_modtype(id, decl) ->
@@ -1607,16 +1619,21 @@ let read_signature modname filename =
(* Return the CRC of the interface of the given compilation unit *)
let crc_of_unit name =
- let ps = find_pers_struct ~check:false name in
- try
- List.assoc name ps.ps_crcs
- with Not_found ->
- assert false
+ let ps = find_pers_struct name in
+ let crco =
+ try
+ List.assoc name ps.ps_crcs
+ with Not_found ->
+ assert false
+ in
+ match crco with
+ None -> assert false
+ | Some crc -> crc
(* Return the list of imported interfaces with their CRCs *)
-let imported_units() =
- Consistbl.extract crc_units
+let imports() =
+ Consistbl.extract !imported_units crc_units
(* Save a signature to a file *)
@@ -1645,12 +1662,12 @@ let save_signature_with_imports sg modname filename imports =
{ ps_name = modname;
ps_sig = sg;
ps_comps = comps;
- ps_crcs = (cmi.cmi_name, crc) :: imports;
+ ps_crcs = (cmi.cmi_name, Some crc) :: imports;
ps_filename = filename;
- ps_flags = cmi.cmi_flags;
- ps_crcs_checked = true } in
+ ps_flags = cmi.cmi_flags } in
Hashtbl.add persistent_structures modname (Some ps);
Consistbl.set crc_units modname crc filename;
+ imported_units := modname :: !imported_units;
sg
with exn ->
close_out oc;
@@ -1658,7 +1675,7 @@ let save_signature_with_imports sg modname filename imports =
raise exn
let save_signature sg modname filename =
- save_signature_with_imports sg modname filename (imported_units())
+ save_signature_with_imports sg modname filename (imports())
(* Folding on environments *)
@@ -1749,11 +1766,10 @@ and fold_cltypes f =
(* Make the initial environment *)
-
-let initial =
+let (initial_safe_string, initial_unsafe_string) =
Predef.build_initial_env
(add_type ~check:false)
- (add_exception ~check:false)
+ (add_extension ?rebind:None ~check:false)
empty
(* Return the environment summary *)
diff --git a/typing/env.mli b/typing/env.mli
index 0197a193cd..eae5bc5fad 100644
--- a/typing/env.mli
+++ b/typing/env.mli
@@ -18,7 +18,7 @@ type summary =
Env_empty
| Env_value of summary * Ident.t * value_description
| Env_type of summary * Ident.t * type_declaration
- | Env_exception of summary * Ident.t * exception_declaration
+ | Env_extension of summary * Ident.t * extension_constructor
| Env_module of summary * Ident.t * module_declaration
| Env_modtype of summary * Ident.t * modtype_declaration
| Env_class of summary * Ident.t * class_declaration
@@ -29,7 +29,8 @@ type summary =
type t
val empty: t
-val initial: t
+val initial_safe_string: t
+val initial_unsafe_string: t
val diff: t -> t -> Ident.t list
type type_descriptions =
@@ -88,7 +89,7 @@ val lookup_label: Longident.t -> t -> label_description
val lookup_all_labels:
Longident.t -> t -> (label_description * (unit -> unit)) list
val lookup_type: Longident.t -> t -> Path.t * type_declaration
-val lookup_module: Longident.t -> t -> Path.t
+val lookup_module: load:bool -> Longident.t -> t -> Path.t
val lookup_modtype: Longident.t -> t -> Path.t * modtype_declaration
val lookup_class: Longident.t -> t -> Path.t * class_declaration
val lookup_cltype: Longident.t -> t -> Path.t * class_type_declaration
@@ -103,7 +104,7 @@ exception Recmodule
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_exception: check:bool -> Ident.t -> exception_declaration -> t -> t
+val add_extension: ?rebind:Path.t -> check:bool -> Ident.t -> extension_constructor -> t -> t
val add_module: ?arg:bool -> Ident.t -> module_type -> t -> t
val add_module_declaration: ?arg:bool -> Ident.t -> module_declaration -> t -> t
val add_modtype: Ident.t -> modtype_declaration -> t -> t
@@ -130,8 +131,8 @@ 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_exception:
- ?rebind:Path.t -> string -> exception_declaration -> t -> Ident.t * t
+val enter_extension:
+ ?rebind:Path.t -> string -> extension_constructor -> t -> Ident.t * t
val enter_module: ?arg:bool -> string -> module_type -> t -> Ident.t * t
val enter_module_declaration:
?arg:bool -> string -> module_declaration -> t -> Ident.t * t
@@ -155,7 +156,7 @@ val read_signature: string -> string -> signature
val save_signature: signature -> string -> string -> signature
(* Arguments: signature, module name, file name. *)
val save_signature_with_imports:
- signature -> string -> string -> (string * Digest.t) list -> signature
+ signature -> string -> string -> (string * Digest.t option) list -> signature
(* Arguments: signature, module name, file name,
imported units with their CRCs. *)
@@ -165,11 +166,12 @@ val crc_of_unit: string -> Digest.t
(* Return the set of compilation units imported, with their CRC *)
-val imported_units: unit -> (string * Digest.t) list
+val imports: unit -> (string * Digest.t option) list
(* Direct access to the table of imported compilation units with their CRC *)
val crc_units: Consistbl.t
+val imported_units: string list ref
(* Summaries -- compact representation of an environment, to be
exported in debugging information. *)
@@ -206,8 +208,8 @@ val mark_constructor_used:
constructor_usage -> string -> type_declaration -> string -> unit
val mark_constructor:
constructor_usage -> t -> string -> constructor_description -> unit
-val mark_exception_used:
- constructor_usage -> exception_declaration -> string -> unit
+val mark_extension_used:
+ constructor_usage -> extension_constructor -> string -> unit
val in_signature: t -> t
diff --git a/typing/envaux.ml b/typing/envaux.ml
index 04d6d256f7..af86fd25be 100644
--- a/typing/envaux.ml
+++ b/typing/envaux.ml
@@ -47,9 +47,9 @@ let rec env_from_summary sum subst =
Env.add_type ~check:false id
(Subst.type_declaration subst desc)
(env_from_summary s subst)
- | Env_exception(s, id, desc) ->
- Env.add_exception ~check:false id
- (Subst.exception_declaration subst desc)
+ | Env_extension(s, id, desc) ->
+ 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 id
diff --git a/typing/includecore.ml b/typing/includecore.ml
index 523cf30c1a..0c5141c05f 100644
--- a/typing/includecore.ml
+++ b/typing/includecore.ml
@@ -148,7 +148,7 @@ let report_type_mismatch0 first second decl ppf err =
| Record_regular -> "regular"
| Record_inlined i -> Printf.sprintf"inlined(tag %i)" i
| Record_float -> "unboxed float"
- | Record_exception p -> Printf.sprintf "exception %s" (Path.name p)
+ | Record_extension p -> Printf.sprintf "exception %s" (Path.name p)
in
pr "Their internal representations differ:@ %s vs %s"
(repr r1)
@@ -217,7 +217,7 @@ let record_representations r1 r2 =
| Record_regular, Record_regular -> true
| Record_inlined i, Record_inlined j -> i = j
| Record_float, Record_float -> true
- | Record_exception _, Record_exception _ -> true
+ | Record_extension _, Record_extension _ -> true
(* allow a different path to support exception rebinding *)
| _ -> false
@@ -246,6 +246,7 @@ let type_declarations ?(equality = false) env name decl1 id decl2 =
1 labels1 labels2 in
if err <> [] || record_representations rep1 rep2 then err else
[Record_representation (rep1, rep2)]
+ | (Type_open, Type_open) -> []
| (_, _) -> [Kind]
in
if err <> [] then err else
@@ -270,26 +271,53 @@ let type_declarations ?(equality = false) env name decl1 id decl2 =
let abstr =
decl2.type_private = Private ||
decl2.type_kind = Type_abstract && decl2.type_manifest = None in
+ let opn = decl2.type_kind = Type_open && decl2.type_manifest = None in
+ let constrained ty = not (Btype.(is_Tvar (repr ty))) in
if List.for_all2
(fun ty (v1,v2) ->
let open Variance in
let imp a b = not a || b in
let (co1,cn1) = get_upper v1 and (co2,cn2) = get_upper v2 in
- imp abstr (imp co1 co2 && imp cn1 cn2) &&
- (abstr || Btype.(is_Tvar (repr ty)) || co1 = co2 && cn1 = cn2) &&
+ (if abstr then (imp co1 co2 && imp cn1 cn2)
+ else if opn || constrained ty then (co1 = co2 && cn1 = cn2)
+ else true) &&
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]
-(* Inclusion between exception declarations *)
+(* Inclusion between extension constructors *)
-let exception_declarations env ed1 ed2 =
- (* note: we use 'Ctype.equal true' now (allow renaming), but
- since the type are closed, this doesn't matter *)
- compare_constructor_arguments env (Ident.create "") [] []
- ed1.exn_args ed2.exn_args
- = []
+let extension_constructors env id ext1 ext2 =
+ let usage =
+ if ext1.ext_private = Private || ext2.ext_private = Public
+ then Env.Positive else Env.Privatize
+ in
+ Env.mark_extension_used usage ext1 (Ident.name id);
+ let ty1 =
+ Btype.newgenty (Tconstr(ext1.ext_type_path, ext1.ext_type_params, ref Mnil))
+ in
+ 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 env (Ident.create "")
+ 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
+ match ext1.ext_private, ext2.ext_private with
+ Private, Public -> false
+ | _, _ -> true
+ else false
+ else false
+ else false
(* Inclusion between class types *)
let encode_val (mut, ty) rem =
diff --git a/typing/includecore.mli b/typing/includecore.mli
index 75e6c1957b..d98455380c 100644
--- a/typing/includecore.mli
+++ b/typing/includecore.mli
@@ -37,8 +37,8 @@ val type_declarations:
?equality:bool ->
Env.t -> string ->
type_declaration -> Ident.t -> type_declaration -> type_mismatch list
-val exception_declarations:
- Env.t -> exception_declaration -> exception_declaration -> bool
+val extension_constructors:
+ Env.t -> Ident.t -> extension_constructor -> extension_constructor -> bool
(*
val class_types:
Env.t -> class_type -> class_type -> bool
diff --git a/typing/includemod.ml b/typing/includemod.ml
index 7f80e3c0f9..57fec56142 100644
--- a/typing/includemod.ml
+++ b/typing/includemod.ml
@@ -22,8 +22,8 @@ type symptom =
| Value_descriptions of Ident.t * value_description * value_description
| Type_declarations of Ident.t * type_declaration
* type_declaration * Includecore.type_mismatch list
- | Exception_declarations of
- Ident.t * exception_declaration * exception_declaration
+ | Extension_constructors of
+ Ident.t * extension_constructor * extension_constructor
| Module_types of module_type * module_type
| Modtype_infos of Ident.t * modtype_declaration * modtype_declaration
| Modtype_permutation
@@ -68,14 +68,13 @@ let type_declarations env cxt subst id decl1 decl2 =
if err <> [] then
raise(Error[cxt, env, Type_declarations(id, decl1, decl2, err)])
-(* Inclusion between exception declarations *)
+(* Inclusion between extension constructors *)
-let exception_declarations env cxt subst id decl1 decl2 =
- Env.mark_exception_used Env.Positive decl1 (Ident.name id);
- let decl2 = Subst.exception_declaration subst decl2 in
- if Includecore.exception_declarations env decl1 decl2
+let extension_constructors env cxt subst id ext1 ext2 =
+ let ext2 = Subst.extension_constructor subst ext2 in
+ if Includecore.extension_constructors env id ext1 ext2
then ()
- else raise(Error[cxt, env, Exception_declarations(id, decl1, decl2)])
+ else raise(Error[cxt, env, Extension_constructors(id, ext1, ext2)])
(* Inclusion between class declarations *)
@@ -124,7 +123,7 @@ let rec normalize_module_path env cxt path =
type field_desc =
Field_value of string
| Field_type of string
- | Field_exception of string
+ | Field_typext of string
| Field_module of string
| Field_modtype of string
| Field_class of string
@@ -133,7 +132,7 @@ type field_desc =
let kind_of_field_desc = function
| Field_value _ -> "value"
| Field_type _ -> "type"
- | Field_exception _ -> "exception"
+ | Field_typext _ -> "extension constructor"
| Field_module _ -> "module"
| Field_modtype _ -> "module type"
| Field_class _ -> "class"
@@ -142,7 +141,7 @@ let kind_of_field_desc = function
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_exception(id, d) -> (id, d.exn_loc, Field_exception(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))
@@ -154,7 +153,7 @@ let is_runtime_component = function
| Sig_modtype(_,_)
| Sig_class_type(_,_,_) -> false
| Sig_value(_,_)
- | Sig_exception(_,_)
+ | Sig_typext(_,_,_)
| Sig_module(_,_,_)
| Sig_class(_, _,_) -> true
@@ -331,11 +330,11 @@ and signatures env cxt subst sig1 sig2 =
Subst.add_module id2 (Pident id1) subst
| Sig_modtype _ ->
Subst.add_modtype id2 (Mty_ident (Pident id1)) subst
- | Sig_exception (id2', decl2) ->
+ | Sig_typext (id2', decl2, _) ->
begin match item1 with
- | Sig_exception (id1', decl1) ->
- let ids1 = Subst.sub_ids_exn decl1 in
- let ids2 = Subst.sub_ids_exn decl2 in
+ | Sig_typext (id1', decl1, _) ->
+ let ids1 = Subst.sub_ids_ext decl1 in
+ let ids2 = Subst.sub_ids_ext decl2 in
equate_subtypes ids1 ids2 subst
| _ -> assert false
end
@@ -368,9 +367,9 @@ and signature_components env cxt subst = function
| (Sig_type(id1, tydecl1, _), Sig_type(id2, tydecl2, _), pos) :: rem ->
type_declarations env cxt subst id1 tydecl1 tydecl2;
signature_components env cxt subst rem
- | (Sig_exception(id1, excdecl1), Sig_exception(id2, excdecl2), pos)
+ | (Sig_typext(id1, ext1, _), Sig_typext(id2, ext2, _), pos)
:: rem ->
- exception_declarations env cxt subst id1 excdecl1 excdecl2;
+ extension_constructors env cxt subst id1 ext1 ext2;
(pos, Tcoerce_none) :: signature_components env cxt subst rem
| (Sig_module(id1, mty1, _), Sig_module(id2, mty2, _), pos) :: rem ->
let cc =
@@ -428,9 +427,9 @@ let _ = Env.check_modtype_inclusion := check_modtype_inclusion
(* Check that an implementation of a compilation unit meets its
interface. *)
-let compunit impl_name impl_sig intf_name intf_sig =
+let compunit env impl_name impl_sig intf_name intf_sig =
try
- signatures Env.initial [] Subst.identity impl_sig intf_sig
+ signatures env [] Subst.identity impl_sig intf_sig
with Error reasons ->
raise(Error(([], Env.empty,Interface_mismatch(impl_name, intf_name))
:: reasons))
@@ -474,13 +473,13 @@ let include_err ppf = function
show_locs (d1.type_loc, d2.type_loc)
(Includecore.report_type_mismatch
"the first" "the second" "declaration") errs
- | Exception_declarations(id, d1, d2) ->
+ | Extension_constructors(id, x1, x2) ->
fprintf ppf
- "@[<hv 2>Exception declarations do not match:@ \
+ "@[<hv 2>Extension declarations do not match:@ \
%a@;<1 -2>is not included in@ %a@]"
- (exception_declaration id) d1
- (exception_declaration id) d2;
- show_locs ppf (d1.exn_loc, d2.exn_loc)
+ (extension_constructor id) x1
+ (extension_constructor id) x2;
+ show_locs ppf (x1.ext_loc, x2.ext_loc)
| Module_types(mty1, mty2)->
fprintf ppf
"@[<hv 2>Modules do not match:@ \
@@ -562,12 +561,12 @@ let include_err ppf (cxt, env, err) =
Printtyp.wrap_printing_env env (fun () ->
fprintf ppf "@[<v>%a%a@]" context (List.rev cxt) include_err err)
-let buffer = ref ""
+let buffer = ref Bytes.empty
let is_big obj =
let size = !Clflags.error_size in
size > 0 &&
begin
- if String.length !buffer < size then buffer := String.create size;
+ if Bytes.length !buffer < size then buffer := Bytes.create size;
try ignore (Marshal.to_buffer !buffer 0 size obj []); false
with _ -> true
end
diff --git a/typing/includemod.mli b/typing/includemod.mli
index 2e00bb0246..7ea48f8619 100644
--- a/typing/includemod.mli
+++ b/typing/includemod.mli
@@ -18,7 +18,8 @@ open Format
val modtypes: Env.t -> module_type -> module_type -> module_coercion
val signatures: Env.t -> signature -> signature -> module_coercion
-val compunit: string -> signature -> string -> signature -> module_coercion
+val compunit:
+ Env.t -> string -> signature -> string -> signature -> module_coercion
val type_declarations:
Env.t -> Ident.t -> type_declaration -> type_declaration -> unit
@@ -27,8 +28,8 @@ type symptom =
| Value_descriptions of Ident.t * value_description * value_description
| Type_declarations of Ident.t * type_declaration
* type_declaration * Includecore.type_mismatch list
- | Exception_declarations of
- Ident.t * exception_declaration * exception_declaration
+ | Extension_constructors of
+ Ident.t * extension_constructor * extension_constructor
| 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 bcf13b1681..4e1e0a4f7a 100644
--- a/typing/mtype.ml
+++ b/typing/mtype.ml
@@ -60,7 +60,7 @@ and strengthen_sig env sg p =
{ decl with type_manifest = manif }
in
Sig_type(id, newdecl, rs) :: strengthen_sig env rem p
- | (Sig_exception(id, d) as sigelt) :: rem ->
+ | (Sig_typext(id, ext, es) as sigelt) :: rem ->
sigelt :: strengthen_sig env rem p
| Sig_module(id, md, rs) :: rem ->
let str = strengthen_decl env md (Pdot(p, Ident.name id, nopos)) in
@@ -128,20 +128,9 @@ let nondep_supertype env mid mty =
| Sig_type(id, d, rs) ->
Sig_type(id, Ctype.nondep_type_decl env mid id (va = Co) d, rs)
:: rem'
- | Sig_exception(id, d) ->
- let d =
- {d with
- exn_args = match d.exn_args with
- | Cstr_tuple l ->
- Cstr_tuple (List.map (Ctype.nondep_type env mid) l)
- | Cstr_record (id, l) ->
- let field l =
- {l with ld_type = Ctype.nondep_type env mid l.ld_type}
- in
- Cstr_record (id, List.map field l)
- }
- in
- Sig_exception(id, d) :: 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'
@@ -219,7 +208,7 @@ and type_paths_sig env p pos sg =
type_paths_sig (Env.add_module_declaration 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_exception _ | Sig_class _) :: 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
@@ -244,7 +233,7 @@ and no_code_needed_sig env sg =
no_code_needed_sig (Env.add_module_declaration id md env) rem
| (Sig_type _ | Sig_modtype _ | Sig_class_type _) :: rem ->
no_code_needed_sig env rem
- | (Sig_exception _ | Sig_class _) :: rem ->
+ | (Sig_typext _ | Sig_class _) :: rem ->
false
@@ -267,13 +256,13 @@ and contains_type_item env = function
Sig_type (_,({type_manifest = None} |
{type_kind = Type_abstract; type_private = Private}),_)
| Sig_modtype _
- | Sig_exception (_, {exn_args = Cstr_record _}) ->
+ | Sig_typext (_, {ext_args = Cstr_record _}, _) ->
raise Exit
| Sig_module (_, {md_type = mty}, _) ->
contains_type env mty
| Sig_value _
| Sig_type _
- | Sig_exception _
+ | Sig_typext _
| Sig_class _
| Sig_class_type _ ->
()
diff --git a/typing/oprint.ml b/typing/oprint.ml
index 8084dff06a..3c2d63708e 100644
--- a/typing/oprint.ml
+++ b/typing/oprint.ml
@@ -223,7 +223,8 @@ and print_simple_out_type ppf =
print_out_type ppf ty;
pp_print_char ppf ')';
pp_close_box ppf ()
- | Otyp_abstract | Otyp_sum _ | Otyp_manifest (_, _) -> ()
+ | Otyp_abstract | Otyp_open
+ | Otyp_sum _ | Otyp_manifest (_, _) -> ()
| Otyp_record lbls -> print_record_decl ppf lbls
| Otyp_module (p, n, tyl) ->
fprintf ppf "@[<1>(module %s" p;
@@ -347,6 +348,7 @@ let out_class_type = ref print_out_class_type
let out_module_type = ref (fun _ -> failwith "Oprint.out_module_type")
let out_sig_item = ref (fun _ -> failwith "Oprint.out_sig_item")
let out_signature = ref (fun _ -> failwith "Oprint.out_signature")
+let out_type_extension = ref (fun _ -> failwith "Oprint.out_type_extension")
let rec print_out_functor ppf =
function
@@ -369,6 +371,28 @@ and print_out_signature ppf =
function
[] -> ()
| [item] -> !out_sig_item ppf item
+ | Osig_typext(ext, Oext_first) :: items ->
+ (* Gather together the extension constructors *)
+ let rec gather_extensions acc items =
+ match items with
+ Osig_typext(ext, Oext_next) :: items ->
+ gather_extensions
+ ((ext.oext_name, ext.oext_args, ext.oext_ret_type) :: acc)
+ items
+ | _ -> (List.rev acc, items)
+ in
+ let exts, items =
+ gather_extensions
+ [(ext.oext_name, ext.oext_args, ext.oext_ret_type)]
+ items
+ in
+ let te =
+ { otyext_name = ext.oext_type_name;
+ otyext_params = ext.oext_type_params;
+ otyext_constructors = exts;
+ otyext_private = ext.oext_private }
+ in
+ fprintf ppf "%a@ %a" !out_type_extension te print_out_signature items
| item :: items ->
fprintf ppf "%a@ %a" !out_sig_item item print_out_signature items
and print_out_sig_item ppf =
@@ -383,8 +407,11 @@ and print_out_sig_item ppf =
(if rs = Orec_next then "and" else "class type")
(if vir_flag then " virtual" else "") print_out_class_params params
name !out_class_type clt
- | Osig_exception (id, tyl) ->
- fprintf ppf "@[<2>exception %a@]" print_out_constr (id, tyl,None)
+ | Osig_typext (ext, Oext_exception) ->
+ fprintf ppf "@[<2>exception %a@]"
+ print_out_constr (ext.oext_name, ext.oext_args, ext.oext_ret_type)
+ | Osig_typext (ext, es) ->
+ print_out_extension_constructor ppf ext
| Osig_modtype (name, Omty_abstract) ->
fprintf ppf "@[<2>module type %s@]" name
| Osig_modtype (name, mty) ->
@@ -413,57 +440,63 @@ and print_out_sig_item ppf =
fprintf ppf "@[<2>%s %a :@ %a%a@]" kwd value_ident name !out_type
ty pr_prims prims
-and print_out_type_decl kwd ppf (name, args, ty, priv, constraints) =
- let print_constraints ppf params =
+and print_out_type_decl kwd ppf td =
+ let print_constraints ppf =
List.iter
(fun (ty1, ty2) ->
fprintf ppf "@ @[<2>constraint %a =@ %a@]" !out_type ty1
!out_type ty2)
- params
+ td.otype_cstrs
in
let type_defined ppf =
- match args with
- [] -> pp_print_string ppf name
- | [arg] -> fprintf ppf "@[%a@ %s@]" type_parameter arg name
+ match td.otype_params with
+ [] -> pp_print_string ppf td.otype_name
+ | [param] -> fprintf ppf "@[%a@ %s@]" type_parameter param td.otype_name
| _ ->
fprintf ppf "@[(@[%a)@]@ %s@]"
- (print_list type_parameter (fun ppf -> fprintf ppf ",@ ")) args name
+ (print_list type_parameter (fun ppf -> fprintf ppf ",@ "))
+ td.otype_params
+ td.otype_name
in
let print_manifest ppf =
function
Otyp_manifest (ty, _) -> fprintf ppf " =@ %a" !out_type ty
| _ -> ()
in
- let print_name_args ppf =
- fprintf ppf "%s %t%a" kwd type_defined print_manifest ty
+ let print_name_params ppf =
+ fprintf ppf "%s %t%a" kwd type_defined print_manifest td.otype_type
in
let ty =
- match ty with
+ match td.otype_type with
Otyp_manifest (_, ty) -> ty
- | _ -> ty
+ | _ -> td.otype_type
in
let print_private ppf = function
Asttypes.Private -> fprintf ppf " private"
- | Asttypes.Public -> () in
+ | Asttypes.Public -> ()
+ in
let print_out_tkind ppf = function
| Otyp_abstract -> ()
| Otyp_record lbls ->
fprintf ppf " =%a %a"
- print_private priv
+ print_private td.otype_private
print_record_decl lbls
| Otyp_sum constrs ->
fprintf ppf " =%a@;<1 2>%a"
- print_private priv
+ print_private td.otype_private
(print_list print_out_constr (fun ppf -> fprintf ppf "@ | ")) constrs
+ | Otyp_open ->
+ fprintf ppf " = .."
| ty ->
fprintf ppf " =%a@;<1 2>%a"
- print_private priv
+ print_private td.otype_private
!out_type ty
in
- fprintf ppf "@[<2>@[<hv 2>%t%a@]%a@]"
- print_name_args
+ fprintf ppf "@[<2>@[<hv 2>%t%a@]%t@]"
+ print_name_params
print_out_tkind ty
- print_constraints constraints
+ print_constraints
+
and print_out_constr ppf (name, tyl,ret_type_opt) =
match ret_type_opt with
| None ->
@@ -484,9 +517,58 @@ and print_out_constr ppf (name, tyl,ret_type_opt) =
tyl print_simple_out_type ret_type
end
+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] ->
+ fprintf ppf "@[%a@ %s@]"
+ print_type_parameter
+ ty_param
+ ext.oext_type_name
+ | _ ->
+ fprintf ppf "@[(@[%a)@]@ %s@]"
+ (print_list print_type_parameter (fun ppf -> fprintf ppf ",@ "))
+ ext.oext_type_params
+ ext.oext_type_name
+ in
+ fprintf ppf "@[<hv 2>type %t +=%s@;<1 2>%a@]"
+ print_extended_type
+ (if ext.oext_private = Asttypes.Private then " private" else "")
+ print_out_constr (ext.oext_name, ext.oext_args, ext.oext_ret_type)
+
+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] ->
+ fprintf ppf "@[%a@ %s@]"
+ print_type_parameter param
+ te.otyext_name
+ | _ ->
+ fprintf ppf "@[(@[%a)@]@ %s@]"
+ (print_list print_type_parameter (fun ppf -> fprintf ppf ",@ "))
+ te.otyext_params
+ te.otyext_name
+ in
+ fprintf ppf "@[<hv 2>type %t +=%s@;<1 2>%a@]"
+ print_extended_type
+ (if te.otyext_private = Asttypes.Private then " private" else "")
+ (print_list print_out_constr (fun ppf -> fprintf ppf "@ | "))
+ te.otyext_constructors
+
let _ = out_module_type := print_out_module_type
let _ = out_signature := print_out_signature
let _ = out_sig_item := print_out_sig_item
+let _ = out_type_extension := print_out_type_extension
(* Phrases *)
@@ -501,6 +583,29 @@ let print_out_exception ppf exn outv =
let rec print_items ppf =
function
[] -> ()
+ | (Osig_typext(ext, Oext_first), None) :: items ->
+ (* Gather together extension constructors *)
+ let rec gather_extensions acc items =
+ match items with
+ (Osig_typext(ext, Oext_next), None) :: items ->
+ gather_extensions
+ ((ext.oext_name, ext.oext_args, ext.oext_ret_type) :: acc)
+ items
+ | _ -> (List.rev acc, items)
+ in
+ let exts, items =
+ gather_extensions
+ [(ext.oext_name, ext.oext_args, ext.oext_ret_type)]
+ items
+ in
+ let te =
+ { otyext_name = ext.oext_type_name;
+ otyext_params = ext.oext_type_params;
+ otyext_constructors = exts;
+ otyext_private = ext.oext_private }
+ in
+ fprintf ppf "@[%a@]" !out_type_extension te;
+ if items <> [] then fprintf ppf "@ %a" print_items items
| (tree, valopt) :: items ->
begin match valopt with
Some v ->
diff --git a/typing/oprint.mli b/typing/oprint.mli
index 56caa60955..1f9ec32b1a 100644
--- a/typing/oprint.mli
+++ b/typing/oprint.mli
@@ -19,6 +19,7 @@ val out_class_type : (formatter -> out_class_type -> unit) ref
val out_module_type : (formatter -> out_module_type -> unit) ref
val out_sig_item : (formatter -> out_sig_item -> unit) ref
val out_signature : (formatter -> out_sig_item list -> unit) ref
+val out_type_extension : (formatter -> out_type_extension -> unit) ref
val out_phrase : (formatter -> out_phrase -> unit) ref
val parenthesized_ident : string -> bool
diff --git a/typing/outcometree.mli b/typing/outcometree.mli
index eae7b2fbeb..18885e8de6 100644
--- a/typing/outcometree.mli
+++ b/typing/outcometree.mli
@@ -44,6 +44,7 @@ type out_value =
type out_type =
| Otyp_abstract
+ | Otyp_open
| Otyp_alias of out_type * string
| Otyp_arrow of string * out_type * out_type
| Otyp_class of bool * out_ident * out_type list
@@ -86,18 +87,37 @@ and out_sig_item =
| Osig_class_type of
bool * string * (string * (bool * bool)) list * out_class_type *
out_rec_status
- | Osig_exception of string * out_type list
+ | Osig_typext of out_extension_constructor * out_ext_status
| Osig_modtype of string * out_module_type
| Osig_module of string * out_module_type * out_rec_status
| Osig_type of out_type_decl * out_rec_status
| Osig_value of string * out_type * string list
and out_type_decl =
- string * (string * (bool * bool)) list * out_type * Asttypes.private_flag *
- (out_type * out_type) list
+ { otype_name: string;
+ otype_params: (string * (bool * bool)) list;
+ otype_type: out_type;
+ otype_private: Asttypes.private_flag;
+ otype_cstrs: (out_type * out_type) list }
+and out_extension_constructor =
+ { oext_name: string;
+ oext_type_name: string;
+ oext_type_params: string list;
+ oext_args: out_type list;
+ oext_ret_type: out_type option;
+ oext_private: Asttypes.private_flag }
+and out_type_extension =
+ { otyext_name: string;
+ otyext_params: string list;
+ otyext_constructors: (string * out_type list * out_type option) list;
+ otyext_private: Asttypes.private_flag }
and out_rec_status =
| Orec_not
| Orec_first
| Orec_next
+and out_ext_status =
+ | Oext_first
+ | Oext_next
+ | Oext_exception
type out_phrase =
| Ophr_eval of out_value * out_type
diff --git a/typing/parmatch.ml b/typing/parmatch.ml
index 64977130f5..8a840b5426 100644
--- a/typing/parmatch.ml
+++ b/typing/parmatch.ml
@@ -110,13 +110,12 @@ and compats ps qs = match ps,qs with
| p::ps, q::qs -> compat p q && compats ps qs
| _,_ -> assert false
+exception Empty (* Empty pattern *)
+
(****************************************)
-(* Utilities for retrieving constructor *)
-(* and record label names *)
+(* Utilities for retrieving type paths *)
(****************************************)
-exception Empty (* Empty pattern *)
-
(* May need a clean copy, cf. PR#4745 *)
let clean_copy ty =
if ty.level = Btype.generic_level then ty
@@ -128,33 +127,6 @@ let get_type_path ty tenv =
| Tconstr (path,_,_) -> path
| _ -> fatal_error "Parmatch.get_type_path"
-let get_type_descr ty tenv =
- match (Ctype.repr ty).desc with
- | Tconstr (path,_,_) -> Env.find_type path tenv
- | _ -> fatal_error "Parmatch.get_type_descr"
-
-let rec get_constr tag ty tenv =
- match get_type_descr ty tenv with
- | {type_kind=Type_variant constr_list} ->
- Datarepr.find_constr_by_tag tag constr_list
- | {type_manifest = Some _} ->
- get_constr tag (Ctype.expand_head_once tenv (clean_copy ty)) tenv
- | _ -> fatal_error "Parmatch.get_constr"
-
-let find_label lbl lbls =
- try
- let l = List.nth lbls lbl.lbl_pos in
- l.Types.ld_id
- with Failure "nth" -> Ident.create "*Unknown label*"
-
-let rec get_record_labels ty tenv =
- match get_type_descr ty tenv with
- | {type_kind = Type_record(lbls, rep)} -> lbls
- | {type_manifest = Some _} ->
- get_record_labels (Ctype.expand_head_once tenv (clean_copy ty)) tenv
- | _ -> fatal_error "Parmatch.get_record_labels"
-
-
(*************************************)
(* Values as patterns pretty printer *)
(*************************************)
@@ -162,16 +134,8 @@ let rec get_record_labels ty tenv =
open Format
;;
-let get_constr_name tag ty tenv = match tag with
-| Cstr_exception (path, _) -> Path.name path
-| _ ->
- try
- let cd = get_constr tag ty tenv in Ident.name cd.cd_id
- with
- | Datarepr.Constr_not_found -> "*Unknown constructor*"
-
-let is_cons tag v = match get_constr_name tag v.pat_type v.pat_env with
-| "::" -> true
+let is_cons = function
+| {cstr_name = "::"} -> true
| _ -> false
let pretty_const c = match c with
@@ -201,14 +165,12 @@ let rec pretty_val ppf v =
| Tpat_constant c -> fprintf ppf "%s" (pretty_const c)
| Tpat_tuple vs ->
fprintf ppf "@[(%a)@]" (pretty_vals ",") vs
- | Tpat_construct (_, {cstr_tag=tag},[]) ->
- let name = get_constr_name tag v.pat_type v.pat_env in
- fprintf ppf "%s" name
- | Tpat_construct (_, {cstr_tag=tag},[w]) ->
- let name = get_constr_name tag v.pat_type v.pat_env in
- fprintf ppf "@[<2>%s@ %a@]" name pretty_arg w
- | Tpat_construct (_, {cstr_tag=tag},vs) ->
- let name = get_constr_name tag v.pat_type v.pat_env in
+ | Tpat_construct (_, cstr, []) ->
+ fprintf ppf "%s" cstr.cstr_name
+ | Tpat_construct (_, cstr, [w]) ->
+ fprintf ppf "@[<2>%s@ %a@]" cstr.cstr_name pretty_arg w
+ | Tpat_construct (_, cstr, vs) ->
+ let name = cstr.cstr_name in
begin match (name, vs) with
("::", [v1;v2]) ->
fprintf ppf "@[%a::@,%a@]" pretty_car v1 pretty_cdr v2
@@ -221,7 +183,7 @@ let rec pretty_val ppf v =
fprintf ppf "@[<2>`%s@ %a@]" l pretty_arg w
| Tpat_record (lvs,_) ->
fprintf ppf "@[{%a}@]"
- (pretty_lvals (get_record_labels v.pat_type v.pat_env))
+ pretty_lvals
(List.filter
(function
| (_,_,{pat_desc=Tpat_any}) -> false (* do not show lbl=_ *)
@@ -236,14 +198,14 @@ let rec pretty_val ppf v =
fprintf ppf "@[(%a|@,%a)@]" pretty_or v pretty_or w
and pretty_car ppf v = match v.pat_desc with
-| Tpat_construct (_,{cstr_tag=tag}, [_ ; _])
- when is_cons tag v ->
+| Tpat_construct (_,cstr, [_ ; _])
+ when is_cons cstr ->
fprintf ppf "(%a)" pretty_val v
| _ -> pretty_val ppf v
and pretty_cdr ppf v = match v.pat_desc with
-| Tpat_construct (_,{cstr_tag=tag}, [v1 ; v2])
- when is_cons tag v ->
+| Tpat_construct (_,cstr, [v1 ; v2])
+ when is_cons cstr ->
fprintf ppf "%a::@,%a" pretty_car v1 pretty_cdr v2
| _ -> pretty_val ppf v
@@ -262,15 +224,13 @@ and pretty_vals sep ppf = function
| v::vs ->
fprintf ppf "%a%s@ %a" pretty_val v sep (pretty_vals sep) vs
-and pretty_lvals lbls ppf = function
+and pretty_lvals ppf = function
| [] -> ()
| [_,lbl,v] ->
- let name = find_label lbl lbls in
- fprintf ppf "%s=%a" (Ident.name name) pretty_val v
+ fprintf ppf "%s=%a" lbl.lbl_name pretty_val v
| (_, lbl,v)::rest ->
- let name = find_label lbl lbls in
fprintf ppf "%s=%a;@ %a"
- (Ident.name name) pretty_val v (pretty_lvals lbls) rest
+ lbl.lbl_name pretty_val v pretty_lvals rest
let top_pretty ppf v =
fprintf ppf "@[%a@]@?" pretty_val v
@@ -661,16 +621,16 @@ let clean_env env =
loop env
let full_match ignore_generalized closing env = match env with
-| ({pat_desc = Tpat_construct (_,{cstr_tag=Cstr_exception _},_)},_)::_ ->
- false
| ({pat_desc = Tpat_construct(_,c,_);pat_type=typ},_) :: _ ->
- if ignore_generalized then
- (* remove generalized constructors;
- those cases will be handled separately *)
- let env = clean_env env in
- List.length env = c.cstr_normal
+ if c.cstr_consts < 0 then false (* extensions *)
else
- List.length env = c.cstr_consts + c.cstr_nonconsts
+ if ignore_generalized then
+ (* remove generalized constructors;
+ those cases will be handled separately *)
+ let env = clean_env env in
+ List.length env = c.cstr_normal
+ else
+ List.length env = c.cstr_consts + c.cstr_nonconsts
| ({pat_desc = Tpat_variant _} as p,_) :: _ ->
let fields =
@@ -768,19 +728,19 @@ let rec pat_of_constrs ex_pat = function
(pat_of_constr ex_pat cstr,
pat_of_constrs ex_pat rem, None)}
-exception Not_an_adt
-
-let rec adt_path env ty =
- match get_type_descr ty env with
- | {type_kind=Type_variant constr_list} ->
- begin match (Ctype.repr ty).desc with
- | Tconstr (path,_,_) ->
- path
- | _ -> assert false end
- | {type_manifest = Some _} ->
- adt_path env (Ctype.expand_head_once env (clean_copy ty))
- | _ -> raise Not_an_adt
-;;
+let rec get_variant_constructors env ty =
+ match (Ctype.repr ty).desc with
+ | Tconstr (path,_,_) -> begin
+ match Env.find_type path env with
+ | {type_kind=Type_variant _} ->
+ let (constrs, _, _) = Env.find_type_descrs path env in
+ constrs
+ | {type_manifest = Some _} ->
+ get_variant_constructors env
+ (Ctype.expand_head_once env (clean_copy ty))
+ | _ -> fatal_error "Parmatch.get_variant_constructors"
+ end
+ | _ -> fatal_error "Parmatch.get_variant_constructors"
let rec map_filter f =
function
@@ -794,18 +754,12 @@ let rec map_filter f =
let complete_constrs p all_tags =
match p.pat_desc with
| Tpat_construct (_,c,_) ->
- begin try
- let not_tags = complete_tags c.cstr_consts c.cstr_nonconsts all_tags in
- let (constrs, _, _) =
- Env.find_type_descrs (adt_path p.pat_env p.pat_type) p.pat_env in
+ let not_tags = complete_tags c.cstr_consts c.cstr_nonconsts all_tags in
+ let constrs = get_variant_constructors p.pat_env c.cstr_res in
map_filter
(fun cnstr ->
if List.mem cnstr.cstr_tag not_tags then Some cnstr else None)
constrs
- with
- | Datarepr.Constr_not_found ->
- fatal_error "Parmatch.complete_constr: constr_not_found"
- end
| _ -> fatal_error "Parmatch.complete_constr"
@@ -825,16 +779,10 @@ let build_other_constant proj make first next p env =
*)
let build_other ext env = match env with
-| ({pat_desc =
- Tpat_construct (lid, ({cstr_tag=Cstr_exception _} as c),_)},_)
- ::_ ->
- make_pat
- (Tpat_construct
- (lid, {c with
- cstr_tag=(Cstr_exception
- (Path.Pident (Ident.create "*exception*"), Location.none))},
- []))
- Ctype.none Env.empty
+| ({pat_desc = Tpat_construct (lid,
+ ({cstr_tag=Cstr_extension _} as c),_)},_) :: _ ->
+ let c = {c with cstr_name = "*extension*"} in
+ make_pat (Tpat_construct(lid, c, [])) Ctype.none Env.empty
| ({pat_desc = Tpat_construct (_, _,_)} as p,_) :: _ ->
begin match ext with
| Some ext when Path.same ext (get_type_path p.pat_type p.pat_env) ->
@@ -1921,7 +1869,7 @@ let rec collect_paths_from_pat r p = match p.pat_desc with
ps
| Tpat_any|Tpat_var _|Tpat_constant _| Tpat_variant (_,None,_) -> r
| Tpat_tuple ps | Tpat_array ps
-| Tpat_construct (_, {cstr_tag=Cstr_exception _}, ps)->
+| Tpat_construct (_, {cstr_tag=Cstr_extension _}, ps)->
List.fold_left collect_paths_from_pat r ps
| Tpat_record (lps,_) ->
List.fold_left
@@ -1990,7 +1938,7 @@ let check_unused tdefs casel =
p.pat_loc Warnings.Unused_pat)
ps
| Used -> ()
- with Empty | Not_an_adt | Not_found | NoGuard -> assert false
+ with Empty | Not_found | NoGuard -> assert false
end ;
if c_guard <> None then
diff --git a/typing/predef.ml b/typing/predef.ml
index 55fe4b880e..bcad58efdd 100644
--- a/typing/predef.ml
+++ b/typing/predef.ml
@@ -35,12 +35,12 @@ and ident_unit = ident_create "unit"
and ident_exn = ident_create "exn"
and ident_array = ident_create "array"
and ident_list = ident_create "list"
-and ident_format6 = ident_create "format6"
and ident_option = ident_create "option"
and ident_nativeint = ident_create "nativeint"
and ident_int32 = ident_create "int32"
and ident_int64 = ident_create "int64"
and ident_lazy_t = ident_create "lazy_t"
+and ident_bytes = ident_create "bytes"
let path_int = Pident ident_int
and path_char = Pident ident_char
@@ -51,12 +51,12 @@ and path_unit = Pident ident_unit
and path_exn = Pident ident_exn
and path_array = Pident ident_array
and path_list = Pident ident_list
-and path_format6 = Pident ident_format6
and path_option = Pident ident_option
and path_nativeint = Pident ident_nativeint
and path_int32 = Pident ident_int32
and path_int64 = Pident ident_int64
and path_lazy_t = Pident ident_lazy_t
+and path_bytes = Pident ident_bytes
let type_int = newgenty (Tconstr(path_int, [], ref Mnil))
and type_char = newgenty (Tconstr(path_char, [], ref Mnil))
@@ -72,6 +72,7 @@ and type_nativeint = newgenty (Tconstr(path_nativeint, [], ref Mnil))
and type_int32 = newgenty (Tconstr(path_int32, [], ref Mnil))
and type_int64 = newgenty (Tconstr(path_int64, [], ref Mnil))
and type_lazy_t t = newgenty (Tconstr(path_lazy_t, [t], ref Mnil))
+and type_bytes = newgenty (Tconstr(path_bytes, [], ref Mnil))
let ident_match_failure = ident_create_predef_exn "Match_failure"
and ident_out_of_memory = ident_create_predef_exn "Out_of_memory"
@@ -119,7 +120,7 @@ and ident_nil = ident_create "[]"
and ident_cons = ident_create "::"
and ident_none = ident_create "None"
and ident_some = ident_create "Some"
-let build_initial_env add_type add_exception empty_env =
+let common_initial_env add_type add_extension empty_env =
let decl_bool =
{decl_abstr with
type_kind = Type_variant([cstr ident_false []; cstr ident_true []])}
@@ -128,7 +129,7 @@ let build_initial_env add_type add_exception empty_env =
type_kind = Type_variant([cstr ident_void []])}
and decl_exn =
{decl_abstr with
- type_kind = Type_variant []}
+ type_kind = Type_open}
and decl_array =
let tvar = newgenvar() in
{decl_abstr with
@@ -143,12 +144,6 @@ let build_initial_env add_type add_exception empty_env =
type_kind =
Type_variant([cstr ident_nil []; cstr ident_cons [tvar; type_list tvar]]);
type_variance = [Variance.covariant]}
- and decl_format6 =
- let params = List.map (newgenvar ?name:None) [();();();();();()] in
- {decl_abstr with
- type_params = params;
- type_arity = 6;
- type_variance = List.map (fun _ -> Variance.full) params}
and decl_option =
let tvar = newgenvar() in
{decl_abstr with
@@ -164,31 +159,36 @@ let build_initial_env add_type add_exception empty_env =
type_variance = [Variance.covariant]}
in
- let add_exception id l =
- add_exception id
- { exn_args = Cstr_tuple l; exn_loc = Location.none; exn_attributes = [] }
+ let add_extension id l =
+ add_extension id
+ { ext_type_path = path_exn;
+ ext_type_params = [];
+ ext_args = Cstr_tuple l;
+ ext_ret_type = None;
+ ext_private = Asttypes.Public;
+ ext_loc = Location.none;
+ ext_attributes = [] }
in
- add_exception ident_match_failure
+ add_extension ident_match_failure
[newgenty (Ttuple[type_string; type_int; type_int])] (
- add_exception ident_out_of_memory [] (
- add_exception ident_stack_overflow [] (
- add_exception ident_invalid_argument [type_string] (
- add_exception ident_failure [type_string] (
- add_exception ident_not_found [] (
- add_exception ident_sys_blocked_io [] (
- add_exception ident_sys_error [type_string] (
- add_exception ident_end_of_file [] (
- add_exception ident_division_by_zero [] (
- add_exception ident_assert_failure
+ add_extension ident_out_of_memory [] (
+ add_extension ident_stack_overflow [] (
+ add_extension ident_invalid_argument [type_string] (
+ add_extension ident_failure [type_string] (
+ add_extension ident_not_found [] (
+ add_extension ident_sys_blocked_io [] (
+ add_extension ident_sys_error [type_string] (
+ add_extension ident_end_of_file [] (
+ add_extension ident_division_by_zero [] (
+ add_extension ident_assert_failure
[newgenty (Ttuple[type_string; type_int; type_int])] (
- add_exception ident_undefined_recursive_module
+ add_extension ident_undefined_recursive_module
[newgenty (Ttuple[type_string; type_int; type_int])] (
add_type ident_int64 decl_abstr (
add_type ident_int32 decl_abstr (
add_type ident_nativeint decl_abstr (
add_type ident_lazy_t decl_lazy_t (
add_type ident_option decl_option (
- add_type ident_format6 decl_format6 (
add_type ident_list decl_list (
add_type ident_array decl_array (
add_type ident_exn decl_exn (
@@ -198,7 +198,14 @@ let build_initial_env add_type add_exception empty_env =
add_type ident_string decl_abstr (
add_type ident_char decl_abstr (
add_type ident_int decl_abstr (
- empty_env)))))))))))))))))))))))))))
+ empty_env))))))))))))))))))))))))))
+
+let build_initial_env add_type add_exception empty_env =
+ let common = common_initial_env add_type add_exception empty_env in
+ let safe_string = add_type ident_bytes decl_abstr common in
+ let decl_bytes_unsafe = {decl_abstr with type_manifest = Some type_string} in
+ let unsafe_string = add_type ident_bytes decl_bytes_unsafe common in
+ (safe_string, unsafe_string)
let builtin_values =
List.map (fun id -> Ident.make_global id; (Ident.name id, id))
diff --git a/typing/predef.mli b/typing/predef.mli
index a2f4724718..9723671165 100644
--- a/typing/predef.mli
+++ b/typing/predef.mli
@@ -17,6 +17,7 @@ open Types
val type_int: type_expr
val type_char: type_expr
val type_string: type_expr
+val type_bytes: type_expr
val type_float: type_expr
val type_bool: type_expr
val type_unit: type_expr
@@ -32,13 +33,13 @@ val type_lazy_t: type_expr -> type_expr
val path_int: Path.t
val path_char: Path.t
val path_string: Path.t
+val path_bytes: Path.t
val path_float: Path.t
val path_bool: Path.t
val path_unit: Path.t
val path_exn: Path.t
val path_array: Path.t
val path_list: Path.t
-val path_format6: Path.t
val path_option: Path.t
val path_nativeint: Path.t
val path_int32: Path.t
@@ -51,12 +52,12 @@ val path_undefined_recursive_module : Path.t
(* To build the initial environment. Since there is a nasty mutual
recursion between predef and env, we break it by parameterizing
- over Env.t, Env.add_type and Env.add_exception. *)
+ over Env.t, Env.add_type and Env.add_extension. *)
val build_initial_env:
(Ident.t -> type_declaration -> 'a -> 'a) ->
- (Ident.t -> exception_declaration -> 'a -> 'a) ->
- 'a -> 'a
+ (Ident.t -> extension_constructor -> 'a -> 'a) ->
+ 'a -> 'a * 'a
(* To initialize linker tables *)
diff --git a/typing/printtyp.ml b/typing/printtyp.ml
index ee39b36ded..c86d245165 100644
--- a/typing/printtyp.ml
+++ b/typing/printtyp.ml
@@ -790,6 +790,7 @@ let rec tree_of_type_decl id decl =
cstrs
| Type_record(l, rep) ->
List.iter (fun l -> mark_loops l.ld_type) l
+ | Type_open -> ()
end;
let type_param =
@@ -807,6 +808,8 @@ let rec tree_of_type_decl id decl =
| Type_variant tll ->
decl.type_private = Private ||
List.exists (fun cd -> cd.cd_res <> None) tll
+ | Type_open ->
+ decl.type_manifest = None
in
let vari =
List.map2
@@ -840,8 +843,15 @@ let rec tree_of_type_decl id decl =
| Type_record(lbls, rep) ->
tree_of_manifest (Otyp_record (List.map tree_of_label lbls)),
decl.type_private
+ | Type_open ->
+ tree_of_manifest Otyp_open,
+ Public
in
- (name, args, ty, priv, constraints)
+ { otype_name = name;
+ otype_params = args;
+ otype_type = ty;
+ otype_private = priv;
+ otype_cstrs = constraints }
and tree_of_constructor_arguments = function
| Cstr_tuple l -> tree_of_typlist false l
@@ -860,12 +870,6 @@ and tree_of_constructor cd =
names := nm;
(name, args, Some ret)
-
-and tree_of_constructor_ret =
- function
- | None -> None
- | Some ret_type -> Some (tree_of_typexp false ret_type)
-
and tree_of_label l =
(Ident.name l.ld_id, l.ld_mutable = Mutable, tree_of_typexp false l.ld_type)
@@ -875,16 +879,55 @@ let tree_of_type_declaration id decl rs =
let type_declaration id ppf decl =
!Oprint.out_sig_item ppf (tree_of_type_declaration id decl Trec_first)
-(* Print an exception declaration *)
+(* Print an extension declaration *)
-let tree_of_exception_declaration id decl =
+let tree_of_extension_constructor id ext es =
reset ();
- mark_loops_constructor_arguments decl.exn_args;
- let tyl = tree_of_constructor_arguments decl.exn_args in
- Osig_exception (Ident.name id, tyl)
+ 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;
+ List.iter mark_loops ty_params;
+ List.iter check_name_of_type (List.map proxy ty_params);
+ mark_loops_constructor_arguments ext.ext_args;
+ may mark_loops ext.ext_ret_type;
+ let type_param =
+ function
+ | Otyp_var (_, id) -> id
+ | _ -> "?"
+ in
+ let ty_params =
+ List.map (fun ty -> type_param (tree_of_typexp false ty)) ty_params
+ in
+ let name = Ident.name id in
+ let args, ret =
+ match ext.ext_ret_type with
+ | None -> (tree_of_constructor_arguments ext.ext_args, None)
+ | Some res ->
+ let nm = !names in
+ names := [];
+ let ret = tree_of_typexp false res in
+ let args = tree_of_constructor_arguments ext.ext_args in
+ names := nm;
+ (args, Some ret)
+ in
+ let ext =
+ { oext_name = name;
+ oext_type_name = ty_name;
+ oext_type_params = ty_params;
+ oext_args = args;
+ oext_ret_type = ret;
+ oext_private = ext.ext_private }
+ in
+ let es =
+ match es with
+ Text_first -> Oext_first
+ | Text_next -> Oext_next
+ | Text_exception -> Oext_exception
+ in
+ Osig_typext (ext, es)
-let exception_declaration id ppf decl =
- !Oprint.out_sig_item ppf (tree_of_exception_declaration id decl)
+let extension_constructor id ppf ext =
+ !Oprint.out_sig_item ppf (tree_of_extension_constructor id ext Text_first)
(* Print a value declaration *)
@@ -1151,8 +1194,8 @@ and trees_of_sigitem = function
[]
| Sig_type(id, decl, rs) ->
[tree_of_type_declaration id decl rs]
- | Sig_exception(id, decl) ->
- [tree_of_exception_declaration id decl]
+ | Sig_typext(id, ext, es) ->
+ [tree_of_extension_constructor id ext es]
| Sig_module(id, md, rs) ->
[tree_of_module id md.md_type rs]
| Sig_modtype(id, decl) ->
diff --git a/typing/printtyp.mli b/typing/printtyp.mli
index 82b8608e54..531b0e9954 100644
--- a/typing/printtyp.mli
+++ b/typing/printtyp.mli
@@ -47,10 +47,10 @@ val tree_of_type_declaration:
Ident.t -> type_declaration -> rec_status -> out_sig_item
*)
val type_declaration: Ident.t -> formatter -> type_declaration -> unit
-val tree_of_exception_declaration:
- Ident.t -> exception_declaration -> out_sig_item
-val exception_declaration:
- Ident.t -> formatter -> exception_declaration -> unit
+val tree_of_extension_constructor:
+ Ident.t -> extension_constructor -> ext_status -> out_sig_item
+val extension_constructor:
+ Ident.t -> formatter -> extension_constructor -> unit
val tree_of_module: Ident.t -> module_type -> rec_status -> out_sig_item
val modtype: formatter -> module_type -> unit
val signature: formatter -> signature -> unit
diff --git a/typing/printtyped.ml b/typing/printtyped.ml
index 9ef36b20aa..608fb44a06 100644
--- a/typing/printtyped.ml
+++ b/typing/printtyped.ml
@@ -171,8 +171,9 @@ let rec core_type i ppf x =
line i ppf "Ptyp_object %a\n" fmt_closed_flag c;
let i = i + 1 in
List.iter
- (fun (s, t) ->
- line i ppf "method %s" s;
+ (fun (s, attrs, t) ->
+ line i ppf "method %s\n" s;
+ attributes i ppf attrs;
core_type (i + 1) ppf t
)
l
@@ -186,7 +187,7 @@ let rec core_type i ppf x =
line i ppf "Ptyp_poly%a\n"
(fun ppf -> List.iter (fun x -> fprintf ppf " '%s" x)) sl;
core_type i ppf ct;
- | Ttyp_package { pack_name = s; pack_fields = l } ->
+ | Ttyp_package { pack_path = s; pack_fields = l } ->
line i ppf "Ptyp_package %a\n" fmt_path s;
list i package_with ppf l;
@@ -288,10 +289,11 @@ and expression i ppf x =
line i ppf "Pexp_apply\n";
expression i ppf e;
list i label_x_expression ppf l;
- | Texp_match (e, l, partial) ->
+ | Texp_match (e, l1, l2, partial) ->
line i ppf "Pexp_match\n";
expression i ppf e;
- list i case ppf l;
+ list i case ppf l1;
+ list i case ppf l2;
| Texp_try (e, l) ->
line i ppf "Pexp_try\n";
expression i ppf e;
@@ -377,12 +379,7 @@ and value_description i ppf x =
core_type (i+1) ppf x.val_desc;
list (i+1) string ppf x.val_prim;
-and type_parameter i ppf (x, _variance) =
- match x with
- | Some x ->
- string i ppf x.txt
- | None ->
- string i ppf "_"
+and type_parameter i ppf (x, _variance) = core_type i ppf x
and type_declaration i ppf x =
line i ppf "type_declaration %a %a\n" fmt_ident x.typ_id fmt_location x.typ_loc;
@@ -408,6 +405,37 @@ and type_kind i ppf x =
| Ttype_record l ->
line i ppf "Ptype_record\n";
list (i+1) label_decl ppf l;
+ | Ttype_open ->
+ line i ppf "Ptype_open\n"
+
+and type_extension i ppf x =
+ line i ppf "type_extension\n";
+ attributes i ppf x.tyext_attributes;
+ let i = i+1 in
+ line i ppf "ptyext_path = %a\n" fmt_path x.tyext_path;
+ line i ppf "ptyext_params =\n";
+ list (i+1) type_parameter ppf x.tyext_params;
+ line i ppf "ptyext_constructors =\n";
+ list (i+1) extension_constructor ppf x.tyext_constructors;
+ line i ppf "ptyext_private = %a\n" fmt_private_flag x.tyext_private;
+
+and extension_constructor i ppf x =
+ line i ppf "extension_constructor %a\n" fmt_location x.ext_loc;
+ attributes i ppf x.ext_attributes;
+ let i = i + 1 in
+ line i ppf "pext_name = \"%a\"\n" fmt_ident x.ext_id;
+ line i ppf "pext_kind =\n";
+ extension_constructor_kind (i + 1) ppf x.ext_kind;
+
+and extension_constructor_kind i ppf x =
+ match x with
+ Text_decl(a, r) ->
+ line i ppf "Pext_decl\n";
+ constructor_arguments (i+1) ppf a;
+ option (i+1) core_type ppf r;
+ | Text_rebind(p, _) ->
+ line i ppf "Pext_rebind\n";
+ line (i+1) ppf "%a\n" fmt_path p;
and class_type i ppf x =
line i ppf "class_type %a\n" fmt_location x.cltyp_loc;
@@ -449,6 +477,9 @@ 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;
+ | Tctf_attribute (s, arg) ->
+ line i ppf "Pctf_attribute \"%s\"\n" s.txt;
+ Printast.payload i ppf arg
and class_description i ppf x =
line i ppf "class_description %a\n" fmt_location x.ci_loc;
@@ -456,7 +487,7 @@ and class_description i ppf x =
let i = i+1 in
line i ppf "pci_virt = %a\n" fmt_virtual_flag x.ci_virt;
line i ppf "pci_params =\n";
- cl_type_parameters (i+1) ppf x.ci_params;
+ list (i+1) type_parameter ppf x.ci_params;
line i ppf "pci_name = \"%s\"\n" x.ci_id_name.txt;
line i ppf "pci_expr =\n";
class_type (i+1) ppf x.ci_expr;
@@ -466,7 +497,7 @@ and class_type_declaration i ppf x =
let i = i+1 in
line i ppf "pci_virt = %a\n" fmt_virtual_flag x.ci_virt;
line i ppf "pci_params =\n";
- cl_type_parameters (i+1) ppf x.ci_params;
+ list (i+1) type_parameter ppf x.ci_params;
line i ppf "pci_name = \"%s\"\n" x.ci_id_name.txt;
line i ppf "pci_expr =\n";
class_type (i+1) ppf x.ci_expr;
@@ -546,7 +577,7 @@ and class_declaration i ppf x =
let i = i+1 in
line i ppf "pci_virt = %a\n" fmt_virtual_flag x.ci_virt;
line i ppf "pci_params =\n";
- cl_type_parameters (i+1) ppf x.ci_params;
+ list (i+1) type_parameter ppf x.ci_params;
line i ppf "pci_name = \"%s\"\n" x.ci_id_name.txt;
line i ppf "pci_expr =\n";
class_expr (i+1) ppf x.ci_expr;
@@ -585,9 +616,12 @@ and signature_item i ppf x =
| Tsig_type l ->
line i ppf "Psig_type\n";
list i type_declaration ppf l;
- | Tsig_exception cd ->
+ | Tsig_typext e ->
+ line i ppf "Psig_typext\n";
+ type_extension i ppf e;
+ | Tsig_exception ext ->
line i ppf "Psig_exception\n";
- constructor_decl i ppf cd
+ extension_constructor i ppf ext
| Tsig_module md ->
line i ppf "Psig_module \"%a\"\n" fmt_ident md.md_id;
attributes i ppf md.md_attributes;
@@ -691,14 +725,12 @@ and structure_item i ppf x =
| Tstr_type l ->
line i ppf "Pstr_type\n";
list i type_declaration ppf l;
- | Tstr_exception cd ->
+ | Tstr_typext te ->
+ line i ppf "Pstr_typext\n";
+ type_extension i ppf te
+ | Tstr_exception ext ->
line i ppf "Pstr_exception\n";
- constructor_decl i ppf cd;
- | Tstr_exn_rebind er ->
- line i ppf "Pstr_exn_rebind \"%a\" %a\n"
- fmt_ident er.exrb_id
- fmt_path er.exrb_path;
- attributes i ppf er.exrb_attributes
+ extension_constructor i ppf ext;
| Tstr_module x ->
line i ppf "Pstr_module\n";
module_binding i ppf x
@@ -748,14 +780,15 @@ and core_type_x_core_type_x_location i ppf (ct1, ct2, l) =
and constructor_decl i ppf {cd_id; cd_name = _; cd_args; cd_res; cd_loc; cd_attributes} =
line i ppf "%a\n" fmt_location cd_loc;
- attributes i ppf cd_attributes;
line (i+1) ppf "%a\n" fmt_ident cd_id;
- begin match cd_args with
- | Cstr_tuple l -> list (i+1) core_type ppf l;
- | Cstr_record l -> list (i+1) label_decl ppf l
- end;
+ attributes i ppf cd_attributes;
+ constructor_arguments (i+1) ppf cd_args;
option (i+1) core_type ppf cd_res
+and constructor_arguments i ppf = function
+ | Cstr_tuple l -> list i core_type ppf l
+ | Cstr_record l -> list i label_decl ppf l
+
and label_decl i ppf {ld_id; ld_name = _; ld_mutable; ld_type; ld_loc; ld_attributes} =
line i ppf "%a\n" fmt_location ld_loc;
attributes i ppf ld_attributes;
@@ -763,13 +796,6 @@ and label_decl i ppf {ld_id; ld_name = _; ld_mutable; ld_type; ld_loc; ld_attrib
line (i+1) ppf "%a" fmt_ident ld_id;
core_type (i+1) ppf ld_type
-and cl_type_parameters i ppf l =
- line i ppf "<params>\n";
- list (i+1) cl_type_parameter ppf l;
-
-and cl_type_parameter i ppf (x, _variance) =
- string_loc i ppf x
-
and longident_x_pattern i ppf (li, _, p) =
line i ppf "%a\n" fmt_longident li;
pattern (i+1) ppf p;
@@ -807,8 +833,9 @@ and ident_x_loc_x_expression_def i ppf (l,_, e) =
and label_x_bool_x_core_type_list i ppf x =
match x with
- Ttag (l, b, ctl) ->
+ Ttag (l, attrs, b, ctl) ->
line i ppf "Rtag \"%s\" %s\n" l (string_of_bool b);
+ attributes (i+1) ppf attrs;
list (i+1) core_type ppf ctl
| Tinherit (ct) ->
line i ppf "Rinherit\n";
diff --git a/typing/subst.ml b/typing/subst.ml
index eb4e7b3c04..0fb9764d33 100644
--- a/typing/subst.ml
+++ b/typing/subst.ml
@@ -50,7 +50,7 @@ let sub_ids decl =
| _ -> []
-let sub_ids_exn exn = sub_ids_args exn.exn_args
+let sub_ids_ext ext = sub_ids_args ext.ext_args
let add_prefixes root ids sub =
List.fold_left
@@ -256,6 +256,7 @@ let type_declaration s decl =
cstrs)
| Type_record(lbls, rep) ->
Type_record (List.map (label_declaration s) lbls, rep)
+ | Type_open -> Type_open
end;
type_manifest =
begin
@@ -337,15 +338,18 @@ let value_description s descr =
val_attributes = attrs s descr.val_attributes;
}
-let exception_declaration s descr =
- let r =
- { exn_args = constructor_arguments s descr.exn_args;
- exn_loc = loc s descr.exn_loc;
- exn_attributes = attrs s descr.exn_attributes;
- }
+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 = ext.ext_attributes;
+ ext_loc = if s.for_saving then Location.none else ext.ext_loc; }
in
- cleanup_types ();
- r
+ cleanup_types ();
+ ext
let rec rename_bound_idents s idents = function
[] -> (List.rev idents, s)
@@ -360,8 +364,8 @@ let rec rename_bound_idents s idents = function
let id' = Ident.rename id in
rename_bound_idents (add_modtype id (Mty_ident(Pident id')) s)
(id' :: idents) sg
- | Sig_exception(id, d) :: sg ->
- let s = rename_types (sub_ids_exn d) s in
+ | Sig_typext(id, d, _) :: sg ->
+ let s = rename_types (sub_ids_ext d) s in
let id' = Ident.rename id in
rename_bound_idents s (id' :: idents) sg
| (Sig_value(id, _) | Sig_class(id, _, _) | Sig_class_type(id, _, _)) :: sg ->
@@ -404,8 +408,8 @@ and signature_component s comp newid =
Sig_value(newid, value_description s d)
| Sig_type(id, d, rs) ->
Sig_type(newid, type_declaration s d, rs)
- | Sig_exception(id, d) ->
- Sig_exception(newid, exception_declaration s d)
+ | 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) ->
diff --git a/typing/subst.mli b/typing/subst.mli
index 4d6762374b..38fad596b8 100644
--- a/typing/subst.mli
+++ b/typing/subst.mli
@@ -43,8 +43,8 @@ val type_expr: t -> type_expr -> type_expr
val class_type: t -> class_type -> class_type
val value_description: t -> value_description -> value_description
val type_declaration: t -> type_declaration -> type_declaration
-val exception_declaration:
- t -> exception_declaration -> exception_declaration
+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
@@ -58,7 +58,7 @@ val compose: t -> t -> t
val sub_ids: type_declaration -> Ident.t list
-val sub_ids_exn: exception_declaration -> Ident.t list
+val sub_ids_ext: extension_constructor -> Ident.t list
val add_prefixes: Path.t -> Ident.t list -> t -> t
diff --git a/typing/typeclass.ml b/typing/typeclass.ml
index 79c8bc7ee8..3bed6ed7d3 100644
--- a/typing/typeclass.ml
+++ b/typing/typeclass.ml
@@ -46,9 +46,9 @@ type error =
| Mutability_mismatch of string * mutable_flag
| No_overriding of string * string
| Duplicate of string * string
- | Extension of string
exception Error of Location.t * Env.t * error
+exception Error_forward of Location.error
open Typedtree
@@ -410,8 +410,13 @@ let rec class_type_field env self_type meths
(mkctf (Tctf_constraint (cty, cty')) :: fields,
val_sig, concr_meths, inher)
- | Pctf_extension (s, _arg) ->
- raise (Error (s.loc, env, Extension s.txt))
+ | Pctf_attribute x ->
+ Typetexp.warning_attribute [x];
+ (mkctf (Tctf_attribute x) :: fields,
+ val_sig, concr_meths, inher)
+
+ | Pctf_extension ext ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
and class_signature env {pcsig_self=sty; pcsig_fields=sign} =
let meths = ref Meths.empty in
@@ -432,11 +437,13 @@ and class_signature env {pcsig_self=sty; pcsig_fields=sign} =
end;
(* Class type fields *)
+ Typetexp.warning_enter_scope ();
let (fields, val_sig, concr_meths, inher) =
List.fold_left (class_type_field env self_type meths)
([], Vars.empty, Concr.empty, [])
sign
in
+ Typetexp.warning_leave_scope ();
let cty = {csig_self = self_type;
csig_vars = val_sig;
csig_concr = concr_meths;
@@ -494,8 +501,8 @@ and class_type env scty =
let clty = class_type env scty in
let typ = Cty_arrow (l, ty, clty.cltyp_type) in
cltyp (Tcty_arrow (l, cty, clty)) typ
- | Pcty_extension (s, _arg) ->
- raise (Error (s.loc, env, Extension s.txt))
+ | Pcty_extension ext ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
let class_type env scty =
delayed_meth_specs := [];
@@ -700,9 +707,13 @@ let rec class_field self_loc cl_num self_type meths vars
end in
(val_env, met_env, par_env, field::fields, concr_meths, warn_vals,
inher, local_meths, local_vals)
-
- | Pcf_extension (s, _arg) ->
- raise (Error (s.loc, val_env, Extension s.txt))
+ | Pcf_attribute x ->
+ Typetexp.warning_attribute [x];
+ (val_env, met_env, par_env,
+ lazy (mkcf (Tcf_attribute x)) :: fields,
+ concr_meths, warn_vals, inher, local_meths, local_vals)
+ | Pcf_extension ext ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
and class_structure cl_num final val_env met_env loc
{ pcstr_self = spat; pcstr_fields = str } =
@@ -751,12 +762,14 @@ and class_structure cl_num final val_env met_env loc
end;
(* Typing of class fields *)
+ Typetexp.warning_enter_scope ();
let (_, _, _, fields, concr_meths, _, inher, _local_meths, _local_vals) =
List.fold_left (class_field self_loc cl_num self_type meths vars)
(val_env, meth_env, par_env, [], Concr.empty, Concr.empty, [],
Concr.empty, Concr.empty)
str
in
+ Typetexp.warning_leave_scope ();
Ctype.unify val_env self_type (Ctype.newvar ());
let sign =
{csig_self = public_self;
@@ -1132,8 +1145,8 @@ and class_expr cl_num val_env met_env scl =
cl_env = val_env;
cl_attributes = scl.pcl_attributes;
}
- | Pcl_extension (s, _arg) ->
- raise (Error (s.loc, val_env, Extension s.txt))
+ | Pcl_extension ext ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
(*******************************)
@@ -1252,12 +1265,16 @@ let class_infos define_class kind
Ctype.begin_class_def ();
(* Introduce class parameters *)
- let params =
- try
- List.map (fun (x, _v) -> enter_type_variable x) cl.pci_params
- with Already_bound loc ->
- raise(Error(loc, env, Repeated_parameter))
+ let ci_params =
+ let make_param (sty, v) =
+ try
+ (transl_type_param env sty, v)
+ with Already_bound ->
+ raise(Error(sty.ptyp_loc, env, Repeated_parameter))
+ in
+ List.map make_param cl.pci_params
in
+ let params = List.map (fun (cty, _) -> cty.ctyp_type) ci_params in
(* Allow self coercions (only for class declarations) *)
let coercion_locs = ref [] in
@@ -1443,12 +1460,12 @@ let class_infos define_class kind
type_attributes = []; (* or keep attrs from cl? *)
}
in
- ((cl, id, clty, ty_id, cltydef, obj_id, obj_abbr, cl_id, cl_abbr,
+ ((cl, id, clty, ty_id, cltydef, obj_id, obj_abbr, cl_id, cl_abbr, ci_params,
arity, pub_meths, List.rev !coercion_locs, expr) :: res,
env)
let final_decl env define_class
- (cl, id, clty, ty_id, cltydef, obj_id, obj_abbr, cl_id, cl_abbr,
+ (cl, id, clty, ty_id, cltydef, obj_id, obj_abbr, cl_id, cl_abbr, ci_params,
arity, pub_meths, coe, expr) =
begin try Ctype.collapse_conj_params env clty.cty_params
@@ -1485,7 +1502,7 @@ let final_decl env define_class
arity, pub_meths, coe, expr,
{ ci_loc = cl.pci_loc;
ci_virt = cl.pci_virt;
- ci_params = cl.pci_params;
+ ci_params = ci_params;
(* TODO : check that we have the correct use of identifiers *)
ci_id_name = cl.pci_name;
ci_id_class = id;
@@ -1818,8 +1835,6 @@ let report_error env ppf = function
| Duplicate (kind, name) ->
fprintf ppf "@[The %s `%s'@ has multiple definitions in this object@]"
kind name
- | Extension s ->
- fprintf ppf "Uninterpreted extension '%s'." s
let report_error env ppf err =
Printtyp.wrap_printing_env env (fun () -> report_error env ppf err)
@@ -1829,6 +1844,8 @@ let () =
(function
| Error (loc, env, err) ->
Some (Location.error_of_printer loc (report_error env) err)
+ | Error_forward err ->
+ Some err
| _ ->
None
)
diff --git a/typing/typeclass.mli b/typing/typeclass.mli
index a4a360bcc5..8e8675fe76 100644
--- a/typing/typeclass.mli
+++ b/typing/typeclass.mli
@@ -104,8 +104,8 @@ type error =
| Mutability_mismatch of string * mutable_flag
| No_overriding of string * string
| Duplicate of string * string
- | Extension of string
exception Error of Location.t * Env.t * error
+exception Error_forward of Location.error
val report_error : Env.t -> formatter -> error -> unit
diff --git a/typing/typecore.ml b/typing/typecore.ml
index c42a921427..6494f22872 100644
--- a/typing/typecore.ml
+++ b/typing/typecore.ml
@@ -37,8 +37,7 @@ type error =
| Wrong_name of string * type_expr * string * Path.t * Longident.t
| Name_type_mismatch of
string * Longident.t * (Path.t * Path.t) * (Path.t * Path.t) list
- | Incomplete_format of string
- | Bad_conversion of string * int * char
+ | Invalid_format of string
| Undefined_method of type_expr * string
| Undefined_inherited_method of string
| Virtual_class of Longident.t
@@ -66,9 +65,11 @@ type error =
| Unqualified_gadt_pattern of Path.t * string
| Invalid_interval
| Invalid_for_loop_index
- | Extension of string
+ | No_value_clauses
+ | Exception_pattern_below_toplevel
exception Error of Location.t * Env.t * error
+exception Error_forward of Location.error
(* Forward declaration, to be filled in by Typemod.type_module *)
@@ -183,13 +184,13 @@ let iter_expression f e =
| Pstr_value (_, pel) -> List.iter binding pel
| Pstr_primitive _
| Pstr_type _
+ | Pstr_typext _
| Pstr_exception _
| Pstr_modtype _
| Pstr_open _
| Pstr_class_type _
| Pstr_attribute _
- | Pstr_extension _
- | Pstr_exn_rebind _ -> ()
+ | Pstr_extension _ -> ()
| Pstr_include {pincl_mod = me}
| Pstr_module {pmb_expr = me} -> module_expr me
| Pstr_recmodule l -> List.iter (fun x -> module_expr x.pmb_expr) l
@@ -215,7 +216,7 @@ let iter_expression f e =
| Pcf_val (_, _, Cfk_concrete (_, e))
| Pcf_method (_, _, Cfk_concrete (_, e)) -> expr e
| Pcf_initializer e -> expr e
- | Pcf_extension _ -> ()
+ | Pcf_attribute _ | Pcf_extension _ -> ()
in
expr e
@@ -257,14 +258,14 @@ let mkexp exp_desc exp_type exp_loc exp_env =
{ exp_desc; exp_type; exp_loc; exp_env; exp_extra = []; exp_attributes = [] }
let option_none ty loc =
- let lid = Longident.Lident "None" in
- let cnone = Env.lookup_constructor lid Env.initial in
- mkexp (Texp_construct(mknoloc lid, cnone, []))
- ty loc Env.initial
+ let lid = Longident.Lident "None"
+ and env = Env.initial_safe_string in
+ let cnone = Env.lookup_constructor lid env in
+ mkexp (Texp_construct(mknoloc lid, cnone, [])) ty loc env
let option_some texp =
let lid = Longident.Lident "Some" in
- let csome = Env.lookup_constructor lid Env.initial in
+ let csome = Env.lookup_constructor lid Env.initial_safe_string in
mkexp ( Texp_construct(mknoloc lid , csome, [texp]) )
(type_option texp.exp_type) texp.exp_loc texp.exp_env
@@ -280,8 +281,7 @@ let extract_concrete_record env ty =
let extract_concrete_variant env ty =
match extract_concrete_typedecl env ty with
- (* exclude exceptions *)
- (p0, p, {type_kind=Type_variant (_::_ as cstrs)}) -> (p0, p, cstrs)
+ (p0, p, {type_kind=Type_variant cstrs}) -> (p0, p, cstrs)
| _ -> raise Not_found
let extract_label_names sexp env ty =
@@ -292,7 +292,11 @@ let extract_label_names sexp env ty =
assert false
let explicit_arity =
- List.exists (fun (s, _) -> s.txt = "ocaml.explicit_arity")
+ List.exists
+ (function
+ | ({txt="ocaml.explicit_arity"|"explicit_arity"; _}, _) -> true
+ | _ -> false
+ )
(* Typing of patterns *)
@@ -568,7 +572,8 @@ let rec expand_path env p =
Some {type_manifest = Some ty} ->
begin match repr ty with
{desc=Tconstr(p,_,_)} -> expand_path env p
- | _ -> assert false
+ | _ -> p
+ (* PR#6394: recursive module may introduce incoherent manifest *)
end
| _ ->
let p' = Env.normalize_path None env p in
@@ -1199,8 +1204,10 @@ let rec type_pat ~constrs ~labels ~no_existentials ~mode ~env sp expected_ty =
unify_pat_types loc !env ty expected_ty;
{ p with pat_extra =
(Tpat_type (path, lid), loc, sp.ppat_attributes) :: p.pat_extra }
- | Ppat_extension (s, _arg) ->
- raise (Error (s.loc, !env, Extension s.txt))
+ | Ppat_exception _ ->
+ raise (Error (loc, !env, Exception_pattern_below_toplevel))
+ | Ppat_extension ext ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
let type_pat ?(allow_existentials=false) ?constrs ?labels
?(lev=get_current_level()) env sp expected_ty =
@@ -1373,7 +1380,7 @@ let rec is_nonexpansive exp =
| Texp_function _ -> true
| Texp_apply(e, (_,None,_)::el) ->
is_nonexpansive e && List.for_all is_nonexpansive_opt (List.map snd3 el)
- | Texp_match(e, cases, _) ->
+ | Texp_match(e, cases, [], _) ->
is_nonexpansive e &&
List.for_all
(fun {c_lhs = _; c_guard; c_rhs} ->
@@ -1409,7 +1416,8 @@ let rec is_nonexpansive exp =
incr count; true
| Tcf_initializer e -> is_nonexpansive e
| Tcf_constraint _ -> true
- | Tcf_inherit _ -> false)
+ | Tcf_inherit _ -> false
+ | Tcf_attribute _ -> true)
fields &&
Vars.fold (fun _ (mut,_,_) b -> decr count; b && mut = Immutable)
vars true &&
@@ -1429,8 +1437,8 @@ and is_nonexpansive_mod mexp =
| Tmod_structure str ->
List.for_all
(fun item -> match item.str_desc with
- | Tstr_eval _ | Tstr_primitive _ | Tstr_type _ | Tstr_modtype _
- | Tstr_open _ | Tstr_class_type _ | Tstr_exn_rebind _ -> true
+ | Tstr_eval _ | Tstr_primitive _ | Tstr_type _
+ | Tstr_modtype _ | Tstr_open _ | 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;_}
@@ -1438,7 +1446,14 @@ and is_nonexpansive_mod mexp =
| Tstr_recmodule id_mod_list ->
List.for_all (fun {mb_expr=m;_} -> is_nonexpansive_mod m)
id_mod_list
- | Tstr_exception _ -> false (* true would be unsound *)
+ | Tstr_exception {ext_kind = Text_decl _} ->
+ false (* true would be unsound *)
+ | Tstr_exception {ext_kind = Text_rebind _} -> true
+ | Tstr_typext te ->
+ List.for_all
+ (function {ext_kind = Text_decl _} -> false
+ | {ext_kind = Text_rebind _} -> true)
+ te.tyext_constructors
| Tstr_class _ -> false (* could be more precise *)
| Tstr_attribute _ -> true
)
@@ -1449,211 +1464,6 @@ and is_nonexpansive_opt = function
None -> true
| Some e -> is_nonexpansive e
-(* Typing format strings for printing or reading.
-
- These format strings are used by functions in modules Printf, Format, and
- Scanf.
-
- (Handling of * modifiers contributed by Thorsten Ohl.) *)
-
-external string_to_format :
- string -> ('a, 'b, 'c, 'd, 'e, 'f) format6 = "%identity"
-external format_to_string :
- ('a, 'b, 'c, 'd, 'e, 'f) format6 -> string = "%identity"
-
-let type_format loc fmt =
-
- let ty_arrow gty ty = newty (Tarrow ("", instance_def gty, ty, Cok)) in
-
- let bad_conversion fmt i c =
- raise (Error (loc, Env.empty, Bad_conversion (fmt, i, c))) in
- let incomplete_format fmt =
- raise (Error (loc, Env.empty, Incomplete_format fmt)) in
-
- let rec type_in_format fmt =
-
- let len = String.length fmt in
-
- let ty_input = newvar ()
- and ty_result = newvar ()
- and ty_aresult = newvar ()
- and ty_uresult = newvar () in
-
- let meta = ref 0 in
-
- let rec scan_format i =
- if i >= len then
- if !meta = 0
- then ty_uresult, ty_result
- else incomplete_format fmt else
- match fmt.[i] with
- | '%' -> scan_opts i (i + 1)
- | _ -> scan_format (i + 1)
- and scan_opts i j =
- if j >= len then incomplete_format fmt else
- match fmt.[j] with
- | '_' -> scan_rest true i (j + 1)
- | _ -> scan_rest false i j
- and scan_rest skip i j =
- let rec scan_flags i j =
- if j >= len then incomplete_format fmt else
- match fmt.[j] with
- | '#' | '0' | '-' | ' ' | '+' -> scan_flags i (j + 1)
- | _ -> scan_width i j
- and scan_width i j = scan_width_or_prec_value scan_precision i j
- and scan_decimal_string scan i j =
- if j >= len then incomplete_format fmt else
- match fmt.[j] with
- | '0' .. '9' -> scan_decimal_string scan i (j + 1)
- | _ -> scan i j
- and scan_width_or_prec_value scan i j =
- if j >= len then incomplete_format fmt else
- match fmt.[j] with
- | '*' ->
- let ty_uresult, ty_result = scan i (j + 1) in
- ty_uresult, ty_arrow Predef.type_int ty_result
- | '-' | '+' -> scan_decimal_string scan i (j + 1)
- | _ -> scan_decimal_string scan i j
- and scan_precision i j =
- if j >= len then incomplete_format fmt else
- match fmt.[j] with
- | '.' -> scan_width_or_prec_value scan_conversion i (j + 1)
- | _ -> scan_conversion i j
- and scan_indication j =
- if j >= len then j - 1 else
- match fmt.[j] with
- | '@' ->
- let k = j + 1 in
- if k >= len then j - 1 else
- begin match fmt.[k] with
- | '%' ->
- let k = k + 1 in
- if k >= len then j - 1 else
- begin match fmt.[k] with
- | '%' | '@' -> k
- | _c -> j - 1
- end
- | _c -> k
- end
- | _c -> j - 1
- and scan_range j =
- let rec scan_closing j =
- if j >= len then incomplete_format fmt else
- match fmt.[j] with
- | ']' -> j
- | '%' ->
- let j = j + 1 in
- if j >= len then incomplete_format fmt else
- begin match fmt.[j] with
- | '%' | '@' -> scan_closing (j + 1)
- | c -> bad_conversion fmt j c
- end
- | c -> scan_closing (j + 1) in
- let scan_first_pos j =
- if j >= len then incomplete_format fmt else
- match fmt.[j] with
- | ']' -> scan_closing (j + 1)
- | c -> scan_closing j in
- let scan_first_neg j =
- if j >= len then incomplete_format fmt else
- match fmt.[j] with
- | '^' -> scan_first_pos (j + 1)
- | c -> scan_first_pos j in
-
- scan_first_neg j
-
- and conversion j ty_arg =
- let ty_uresult, ty_result = scan_format (j + 1) in
- ty_uresult,
- if skip then ty_result else ty_arrow ty_arg ty_result
-
- and conversion_a j ty_e ty_arg =
- let ty_uresult, ty_result = conversion j ty_arg in
- let ty_a = ty_arrow ty_input (ty_arrow ty_e ty_aresult) in
- ty_uresult, ty_arrow ty_a ty_result
-
- and conversion_r j ty_e ty_arg =
- let ty_uresult, ty_result = conversion j ty_arg in
- let ty_r = ty_arrow ty_input ty_e in
- ty_arrow ty_r ty_uresult, ty_result
-
- and scan_conversion i j =
- if j >= len then incomplete_format fmt else
- match fmt.[j] with
- | '%' | '@' | '!' | ',' -> scan_format (j + 1)
- | 's' | 'S' ->
- let j = scan_indication (j + 1) in
- conversion j Predef.type_string
- | '[' ->
- let j = scan_range (j + 1) in
- let j = scan_indication (j + 1) in
- conversion j Predef.type_string
- | 'c' | 'C' -> conversion j Predef.type_char
- | 'd' | 'i' | 'o' | 'u' | 'x' | 'X' | 'N' ->
- conversion j Predef.type_int
- | 'f' | 'e' | 'E' | 'g' | 'G' | 'F' -> conversion j Predef.type_float
- | 'B' | 'b' -> conversion j Predef.type_bool
- | 'a' | 'r' as conv ->
- let conversion =
- if conv = 'a' then conversion_a else conversion_r in
- let ty_e = newvar () in
- let j = j + 1 in
- if j >= len then conversion (j - 1) ty_e ty_e else begin
- match fmt.[j] with
-(* | 'a' | 'A' -> conversion j ty_e (Predef.type_array ty_e)
- | 'l' | 'L' -> conversion j ty_e (Predef.type_list ty_e)
- | 'o' | 'O' -> conversion j ty_e (Predef.type_option ty_e)*)
- | _ -> conversion (j - 1) ty_e ty_e end
-(* | 'r' ->
- let ty_e = newvar () in
- let j = j + 1 in
- if j >= len then conversion_r (j - 1) ty_e ty_e else begin
- match fmt.[j] with
- | 'a' | 'A' -> conversion_r j ty_e (Pref.type_array ty_e)
- | 'l' | 'L' -> conversion_r j ty_e (Pref.type_list ty_e)
- | 'o' | 'O' -> conversion_r j ty_e (Pref.type_option ty_e)
- | _ -> conversion_r (j - 1) ty_e ty_e end *)
- | 't' -> conversion j (ty_arrow ty_input ty_aresult)
- | 'l' | 'n' | 'L' as c ->
- let j = j + 1 in
- if j >= len then conversion (j - 1) Predef.type_int else begin
- match fmt.[j] with
- | 'd' | 'i' | 'o' | 'u' | 'x' | 'X' ->
- let ty_arg =
- match c with
- | 'l' -> Predef.type_int32
- | 'n' -> Predef.type_nativeint
- | _ -> Predef.type_int64 in
- conversion j ty_arg
- | c -> conversion (j - 1) Predef.type_int
- end
- | '{' | '(' as c ->
- let j = j + 1 in
- if j >= len then incomplete_format fmt else
- let sj =
- Printf.CamlinternalPr.Tformat.sub_format
- (fun fmt -> incomplete_format (format_to_string fmt))
- (fun fmt -> bad_conversion (format_to_string fmt))
- c (string_to_format fmt) j in
- let sfmt = String.sub fmt j (sj - 2 - j) in
- let ty_sfmt = type_in_format sfmt in
- begin match c with
- | '{' -> conversion (sj - 1) ty_sfmt
- | _ -> incr meta; conversion (j - 1) ty_sfmt end
- | ')' when !meta > 0 -> decr meta; scan_format (j + 1)
- | c -> bad_conversion fmt i c in
- scan_flags i j in
-
- let ty_ureader, ty_args = scan_format 0 in
- newty
- (Tconstr
- (Predef.path_format6,
- [ ty_args; ty_input; ty_aresult;
- ty_ureader; ty_uresult; ty_result; ],
- ref Mnil)) in
-
- type_in_format fmt
-
(* Approximate the type of an expression, for better recursion *)
let rec approx_type env sty =
@@ -1828,7 +1638,8 @@ let iter_ppat f p =
| Ppat_or (p1,p2) -> f p1; f p2
| Ppat_variant (_, arg) | Ppat_construct (_, arg) -> may f arg
| Ppat_tuple lst -> List.iter f lst
- | Ppat_alias (p,_) | Ppat_constraint (p,_) | Ppat_lazy p -> f p
+ | Ppat_exception p | Ppat_alias (p,_)
+ | Ppat_constraint (p,_) | Ppat_lazy p -> f p
| Ppat_record (args, flag) -> List.iter (fun (_,p) -> f p) args
let contains_polymorphic_variant p =
@@ -1911,9 +1722,10 @@ let rec type_exp env sexp =
and type_expect ?in_function env sexp ty_expected =
let previous_saved_types = Cmt_format.get_saved_types () in
- let prev_warnings = Typetexp.warning_attribute sexp.pexp_attributes in
+ Typetexp.warning_enter_scope ();
+ Typetexp.warning_attribute sexp.pexp_attributes;
let exp = type_expect_ ?in_function env sexp ty_expected in
- may Warnings.restore prev_warnings;
+ Typetexp.warning_leave_scope ();
Cmt_format.set_saved_types
(Cmt_format.Partial_expression exp :: previous_saved_types);
exp
@@ -1968,24 +1780,32 @@ and type_expect_ ?in_function env sexp ty_expected =
exp_attributes = sexp.pexp_attributes;
exp_env = env }
end
- | Pexp_constant(Const_string (s, _) as cst) ->
- let ty_exp = expand_head env ty_expected in
- let ty =
- (* Terrible hack for format strings *)
- match ty_exp.desc with
- Tconstr(path, _, _) when Path.same path Predef.path_format6 ->
- if !Clflags.principal && ty_exp.level <> generic_level then
- Location.prerr_warning loc
- (Warnings.Not_principal "this coercion to format6");
- type_format loc s
- | _ -> instance_def Predef.type_string
- in
+ | Pexp_constant(Const_string (str, _) as cst) -> (
+ (* 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
+ 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
+ Location.prerr_warning loc
+ (Warnings.Not_principal "this coercion to format6");
+ true
+ | _ -> false
+ in
+ if is_format then
+ let format_parsetree =
+ { (type_format loc str env) with pexp_loc = sexp.pexp_loc } in
+ type_expect ?in_function env format_parsetree ty_expected
+ else
rue {
exp_desc = Texp_constant cst;
exp_loc = loc; exp_extra = [];
- exp_type = ty;
+ exp_type = instance_def Predef.type_string;
exp_attributes = sexp.pexp_attributes;
exp_env = env }
+ )
| Pexp_constant cst ->
rue {
exp_desc = Texp_constant cst;
@@ -2091,11 +1911,25 @@ and type_expect_ ?in_function env sexp ty_expected =
end_def ();
if is_nonexpansive arg then generalize arg.exp_type
else generalize_expansive env arg.exp_type;
- let cases, partial =
- type_cases env arg.exp_type ty_expected true loc caselist
+ 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
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, cases, partial);
+ exp_desc = Texp_match(arg, val_cases, exn_cases, partial);
exp_loc = loc; exp_extra = [];
exp_type = instance env ty_expected;
exp_attributes = sexp.pexp_attributes;
@@ -2828,8 +2662,8 @@ and type_expect_ ?in_function env sexp ty_expected =
sexp.pexp_attributes) ::
exp.exp_extra;
}
- | Pexp_extension (s, _arg) ->
- raise (Error (s.loc, env, Extension s.txt))
+ | Pexp_extension ext ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
and type_function ?in_function loc attrs env ty_expected l caselist =
let (loc_fun, ty_fun) =
@@ -2901,6 +2735,240 @@ and type_label_access env loc srecord lid =
(Label.disambiguate lid env opath) labels in
(record, label, opath)
+(* Typing format strings for printing or reading.
+ These formats are used by functions in modules Printf, Format, and Scanf.
+ (Handling of * modifiers contributed by Thorsten Ohl.) *)
+
+and type_format loc str env =
+ let loc = {loc with Location.loc_ghost = true} in
+ try
+ CamlinternalFormatBasics.(CamlinternalFormat.(
+ let mk_exp_loc pexp_desc = {
+ pexp_desc = pexp_desc;
+ pexp_loc = loc;
+ pexp_attributes = [];
+ } and mk_lid_loc lid = {
+ txt = lid;
+ loc = loc;
+ } in
+ let mk_constr name args =
+ let lid = Longident.(Ldot(Lident "CamlinternalFormatBasics", name)) in
+ let arg = match args with
+ | [] -> None
+ | [ e ] -> Some e
+ | _ :: _ :: _ -> 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 (Const_int n)
+ and mk_string str = mk_cst (Const_string (str, None))
+ and mk_char chr = mk_cst (Const_char chr) in
+ let rec mk_formatting_lit fmting = match fmting with
+ | Close_box ->
+ mk_constr "Close_box" []
+ | Close_tag ->
+ mk_constr "Close_tag" []
+ | Break (org, ns, ni) ->
+ mk_constr "Break" [ mk_string org; mk_int ns; mk_int ni ]
+ | FFlush ->
+ mk_constr "FFlush" []
+ | Force_newline ->
+ mk_constr "Force_newline" []
+ | Flush_newline ->
+ mk_constr "Flush_newline" []
+ | Magic_size (org, sz) ->
+ mk_constr "Magic_size" [ mk_string org; mk_int sz ]
+ | Escaped_at ->
+ mk_constr "Escaped_at" []
+ | Escaped_percent ->
+ mk_constr "Escaped_percent" []
+ | Scan_indic c ->
+ mk_constr "Scan_indic" [ mk_char c ]
+ and mk_formatting_gen : type a b c d e f .
+ (a, b, c, d, e, f) formatting_gen -> Parsetree.expression =
+ fun fmting -> match fmting with
+ | Open_tag (Format (fmt', str')) ->
+ mk_constr "Open_tag" [ mk_format fmt' str' ]
+ | Open_box (Format (fmt', str')) ->
+ mk_constr "Open_box" [ mk_format fmt' str' ]
+ and mk_format : type a b c d e f .
+ (a, b, c, d, e, f) CamlinternalFormatBasics.fmt -> string ->
+ Parsetree.expression = fun fmt str ->
+ mk_constr "Format" [ mk_fmt fmt; mk_string str ]
+ and mk_side side = match side with
+ | Left -> mk_constr "Left" []
+ | Right -> mk_constr "Right" []
+ | Zeros -> mk_constr "Zeros" []
+ and mk_iconv iconv = match iconv with
+ | Int_d -> mk_constr "Int_d" [] | Int_pd -> mk_constr "Int_pd" []
+ | Int_sd -> mk_constr "Int_sd" [] | Int_i -> mk_constr "Int_i" []
+ | Int_pi -> mk_constr "Int_pi" [] | Int_si -> mk_constr "Int_si" []
+ | 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" []
+ and mk_fconv fconv = match fconv with
+ | Float_f -> mk_constr "Float_f" []
+ | Float_pf -> mk_constr "Float_pf" []
+ | Float_sf -> mk_constr "Float_sf" []
+ | Float_e -> mk_constr "Float_e" []
+ | Float_pe -> mk_constr "Float_pe" []
+ | Float_se -> mk_constr "Float_se" []
+ | Float_E -> mk_constr "Float_E" []
+ | Float_pE -> mk_constr "Float_pE" []
+ | Float_sE -> mk_constr "Float_sE" []
+ | Float_g -> mk_constr "Float_g" []
+ | Float_pg -> mk_constr "Float_pg" []
+ | Float_sg -> mk_constr "Float_sg" []
+ | Float_G -> mk_constr "Float_G" []
+ | Float_pG -> mk_constr "Float_pG" []
+ | Float_sG -> mk_constr "Float_sG" []
+ | Float_F -> mk_constr "Float_F" []
+ and mk_counter cnt = match cnt with
+ | Line_counter -> mk_constr "Line_counter" []
+ | Char_counter -> mk_constr "Char_counter" []
+ | Token_counter -> mk_constr "Token_counter" []
+ and mk_int_opt n_opt = match n_opt with
+ | None ->
+ let lid_loc = mk_lid_loc (Longident.Lident "None") in
+ mk_exp_loc (Pexp_construct (lid_loc, None))
+ | Some n ->
+ let lid_loc = mk_lid_loc (Longident.Lident "Some") in
+ mk_exp_loc (Pexp_construct (lid_loc, Some (mk_int n)))
+ and mk_fmtty : type a b c d e f g h i j k l .
+ (a, b, c, d, e, f, g, h, i, j, k, l) fmtty_rel -> Parsetree.expression =
+ fun fmtty -> match fmtty with
+ | Char_ty rest -> mk_constr "Char_ty" [ mk_fmtty rest ]
+ | String_ty rest -> mk_constr "String_ty" [ mk_fmtty rest ]
+ | Int_ty rest -> mk_constr "Int_ty" [ mk_fmtty rest ]
+ | Int32_ty rest -> mk_constr "Int32_ty" [ mk_fmtty rest ]
+ | Nativeint_ty rest -> mk_constr "Nativeint_ty" [ mk_fmtty rest ]
+ | Int64_ty rest -> mk_constr "Int64_ty" [ mk_fmtty rest ]
+ | Float_ty rest -> mk_constr "Float_ty" [ mk_fmtty rest ]
+ | Bool_ty rest -> mk_constr "Bool_ty" [ mk_fmtty rest ]
+ | Alpha_ty rest -> mk_constr "Alpha_ty" [ mk_fmtty rest ]
+ | Theta_ty rest -> mk_constr "Theta_ty" [ mk_fmtty rest ]
+ | Reader_ty rest -> mk_constr "Reader_ty" [ mk_fmtty rest ]
+ | Ignored_reader_ty rest ->
+ mk_constr "Ignored_reader_ty" [ mk_fmtty rest ]
+ | Format_arg_ty (sub_fmtty, rest) ->
+ mk_constr "Format_arg_ty" [ mk_fmtty sub_fmtty; mk_fmtty rest ]
+ | Format_subst_ty (sub_fmtty1, sub_fmtty2, rest) ->
+ mk_constr "Format_subst_ty"
+ [ mk_fmtty sub_fmtty1; mk_fmtty sub_fmtty2; mk_fmtty rest ]
+ | End_of_fmtty -> mk_constr "End_of_fmtty" []
+ and mk_ignored : type a b c d e f .
+ (a, b, c, d, e, f) ignored -> Parsetree.expression =
+ fun ign -> match ign with
+ | Ignored_char ->
+ mk_constr "Ignored_char" []
+ | Ignored_caml_char ->
+ mk_constr "Ignored_caml_char" []
+ | Ignored_string pad_opt ->
+ mk_constr "Ignored_string" [ mk_int_opt pad_opt ]
+ | Ignored_caml_string pad_opt ->
+ mk_constr "Ignored_caml_string" [ mk_int_opt pad_opt ]
+ | Ignored_int (iconv, pad_opt) ->
+ mk_constr "Ignored_int" [ mk_iconv iconv; mk_int_opt pad_opt ]
+ | Ignored_int32 (iconv, pad_opt) ->
+ mk_constr "Ignored_int32" [ mk_iconv iconv; mk_int_opt pad_opt ]
+ | Ignored_nativeint (iconv, pad_opt) ->
+ mk_constr "Ignored_nativeint" [ mk_iconv iconv; mk_int_opt pad_opt ]
+ | Ignored_int64 (iconv, pad_opt) ->
+ mk_constr "Ignored_int64" [ mk_iconv iconv; mk_int_opt pad_opt ]
+ | Ignored_float (pad_opt, prec_opt) ->
+ mk_constr "Ignored_float" [ mk_int_opt pad_opt; mk_int_opt prec_opt ]
+ | Ignored_bool ->
+ mk_constr "Ignored_bool" []
+ | Ignored_format_arg (pad_opt, fmtty) ->
+ mk_constr "Ignored_format_arg" [ mk_int_opt pad_opt; mk_fmtty fmtty ]
+ | Ignored_format_subst (pad_opt, fmtty) ->
+ mk_constr "Ignored_format_subst" [
+ mk_int_opt pad_opt; mk_fmtty fmtty ]
+ | Ignored_reader ->
+ mk_constr "Ignored_reader" []
+ | Ignored_scan_char_set (width_opt, char_set) ->
+ mk_constr "Ignored_scan_char_set" [
+ mk_int_opt width_opt; mk_string char_set ]
+ | Ignored_scan_get_counter counter ->
+ mk_constr "Ignored_scan_get_counter" [
+ mk_counter counter
+ ]
+ and mk_padding : type x y . (x, y) padding -> Parsetree.expression =
+ fun pad -> match pad with
+ | No_padding -> mk_constr "No_padding" []
+ | Lit_padding (s, w) -> mk_constr "Lit_padding" [ mk_side s; mk_int w ]
+ | Arg_padding s -> mk_constr "Arg_padding" [ mk_side s ]
+ and mk_precision : type x y . (x, y) precision -> Parsetree.expression =
+ fun prec -> match prec with
+ | No_precision -> mk_constr "No_precision" []
+ | Lit_precision w -> mk_constr "Lit_precision" [ mk_int w ]
+ | Arg_precision -> mk_constr "Arg_precision" []
+ and mk_fmt : type a b c d e f .
+ (a, b, c, d, e, f) fmt -> Parsetree.expression =
+ fun fmt -> match fmt with
+ | Char rest ->
+ mk_constr "Char" [ mk_fmt rest ]
+ | Caml_char rest ->
+ mk_constr "Caml_char" [ mk_fmt rest ]
+ | String (pad, rest) ->
+ mk_constr "String" [ mk_padding pad; mk_fmt rest ]
+ | Caml_string (pad, rest) ->
+ mk_constr "Caml_string" [ mk_padding pad; mk_fmt rest ]
+ | Int (iconv, pad, prec, rest) ->
+ mk_constr "Int" [
+ mk_iconv iconv; mk_padding pad; mk_precision prec; mk_fmt rest ]
+ | Int32 (iconv, pad, prec, rest) ->
+ mk_constr "Int32" [
+ mk_iconv iconv; mk_padding pad; mk_precision prec; mk_fmt rest ]
+ | Nativeint (iconv, pad, prec, rest) ->
+ mk_constr "Nativeint" [
+ mk_iconv iconv; mk_padding pad; mk_precision prec; mk_fmt rest ]
+ | Int64 (iconv, pad, prec, rest) ->
+ mk_constr "Int64" [
+ mk_iconv iconv; mk_padding pad; mk_precision prec; mk_fmt rest ]
+ | Float (fconv, pad, prec, rest) ->
+ mk_constr "Float" [
+ mk_fconv fconv; mk_padding pad; mk_precision prec; mk_fmt rest ]
+ | Bool rest ->
+ mk_constr "Bool" [ mk_fmt rest ]
+ | Flush rest ->
+ mk_constr "Flush" [ mk_fmt rest ]
+ | String_literal (s, rest) ->
+ mk_constr "String_literal" [ mk_string s; mk_fmt rest ]
+ | Char_literal (c, rest) ->
+ mk_constr "Char_literal" [ mk_char c; mk_fmt rest ]
+ | Format_arg (pad_opt, fmtty, rest) ->
+ mk_constr "Format_arg" [
+ mk_int_opt pad_opt; mk_fmtty fmtty; mk_fmt rest ]
+ | Format_subst (pad_opt, fmtty, rest) ->
+ mk_constr "Format_subst" [
+ mk_int_opt pad_opt; mk_fmtty fmtty; mk_fmt rest ]
+ | Alpha rest ->
+ mk_constr "Alpha" [ mk_fmt rest ]
+ | Theta rest ->
+ mk_constr "Theta" [ mk_fmt rest ]
+ | Formatting_lit (fmting, rest) ->
+ mk_constr "Formatting_lit" [ mk_formatting_lit fmting; mk_fmt rest ]
+ | Formatting_gen (fmting, rest) ->
+ mk_constr "Formatting_gen" [ mk_formatting_gen fmting; mk_fmt rest ]
+ | Reader rest ->
+ mk_constr "Reader" [ mk_fmt rest ]
+ | Scan_char_set (width_opt, char_set, rest) ->
+ mk_constr "Scan_char_set" [
+ mk_int_opt width_opt; mk_string char_set; mk_fmt rest ]
+ | Scan_get_counter (cnt, rest) ->
+ mk_constr "Scan_get_counter" [ mk_counter cnt; mk_fmt rest ]
+ | Ignored_param (ign, rest) ->
+ mk_constr "Ignored_param" [ mk_ignored ign; mk_fmt rest ]
+ | End_of_format ->
+ mk_constr "End_of_format" []
+ in
+ let Fmt_EBB fmt = fmt_ebb_of_string str in
+ mk_constr "Format" [ mk_fmt fmt; mk_string str ]
+ ))
+ with Failure msg ->
+ raise (Error (loc, env, Invalid_format msg))
+
and type_label_exp create env loc ty_expected
(lid, label, sarg) =
(* Here also ty_expected may be at generic_level *)
@@ -3764,12 +3832,8 @@ let report_error env ppf = function
(function ppf ->
fprintf ppf "but a %s was expected belonging to the %s type"
name kind)
- | Incomplete_format s ->
- fprintf ppf "Premature end of format string ``%S''" s
- | Bad_conversion (fmt, i, c) ->
- fprintf ppf
- "Bad conversion %%%c, at char number %d \
- in format string ``%s''" c i fmt
+ | Invalid_format msg ->
+ fprintf ppf "%s" msg
| Undefined_method (ty, me) ->
reset_and_mark_loops ty;
fprintf ppf
@@ -3877,8 +3941,12 @@ let report_error env ppf = function
| Invalid_for_loop_index ->
fprintf ppf
"@[Invalid for-loop index: only variables and _ are allowed.@]"
- | Extension s ->
- fprintf ppf "Uninterpreted extension '%s'." s
+ | No_value_clauses ->
+ fprintf ppf
+ "None of the patterns in this 'match' expression match values."
+ | Exception_pattern_below_toplevel ->
+ fprintf ppf
+ "@[Exception patterns must be at the top level of a match case.@]"
let report_error env ppf err =
wrap_printing_env env (fun () -> report_error env ppf err)
@@ -3888,6 +3956,8 @@ let () =
(function
| Error (loc, env, err) ->
Some (Location.error_of_printer loc (report_error env) err)
+ | Error_forward err ->
+ Some err
| _ ->
None
)
diff --git a/typing/typecore.mli b/typing/typecore.mli
index 8dae2c9883..4ce6b1fc36 100644
--- a/typing/typecore.mli
+++ b/typing/typecore.mli
@@ -79,8 +79,7 @@ type error =
| Wrong_name of string * type_expr * string * Path.t * Longident.t
| Name_type_mismatch of
string * Longident.t * (Path.t * Path.t) * (Path.t * Path.t) list
- | Incomplete_format of string
- | Bad_conversion of string * int * char
+ | Invalid_format of string
| Undefined_method of type_expr * string
| Undefined_inherited_method of string
| Virtual_class of Longident.t
@@ -108,9 +107,11 @@ type error =
| Unqualified_gadt_pattern of Path.t * string
| Invalid_interval
| Invalid_for_loop_index
- | Extension of string
+ | No_value_clauses
+ | Exception_pattern_below_toplevel
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}. *)
diff --git a/typing/typedecl.ml b/typing/typedecl.ml
index 5dcffd1cbe..09fd73f64c 100644
--- a/typing/typedecl.ml
+++ b/typing/typedecl.ml
@@ -33,14 +33,17 @@ type error =
| Null_arity_external
| Missing_native_external
| Unbound_type_var of type_expr * type_declaration
- | Unbound_exception of Longident.t
- | Not_an_exception of Longident.t
+ | Not_open_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
+ | Rebind_mismatch of Longident.t * Path.t * Path.t
+ | Rebind_private of Longident.t
| Bad_variance of int * (bool * bool * bool) * (bool * bool * bool)
| Unavailable_type_constructor of Path.t
| Bad_fixed_type of string
- | Unbound_type_var_exc of type_expr * type_expr
+ | Unbound_type_var_ext of type_expr * extension_constructor
| Varying_anonymous
- | Exception_constructor_with_result
open Typedtree
@@ -133,45 +136,14 @@ module StringSet =
let compare (x:t) y = compare x y
end)
-module StringMap =
- Map.Make(struct
- type t = string
- let compare (x:t) y = compare x y
- end)
-
-let make_params sdecl =
- try
- List.map
- (fun (x, _) ->
- match x with
- | None -> Ctype.new_global_var ~name:"_" ()
- | Some x -> enter_type_variable x)
- sdecl.ptype_params
- with Already_bound loc ->
- raise(Error(loc, Repeated_parameter))
-
-let freevars bound kind =
- let open Ast_mapper in
- let vars = ref StringMap.empty in
- let bound = ref bound in
- let super = default_mapper in
- let typ m ct =
- match ct.ptyp_desc with
- | Ptyp_var s ->
- if not (StringSet.mem s !bound) then
- vars := StringMap.add s ct.ptyp_loc !vars;
- ct
- | Ptyp_poly (sl, t) ->
- let old_bound = !bound in
- List.iter (fun s -> bound := StringSet.add s !bound) sl;
- ignore (m.typ m t);
- bound := old_bound;
- ct
- | _ -> super.typ m ct
+let make_params env params =
+ let make_param (sty, v) =
+ try
+ (transl_type_param env sty, v)
+ with Already_bound ->
+ raise(Error(sty.ptyp_loc, Repeated_parameter))
in
- let mapper = {super with typ} in
- ignore (mapper.type_kind mapper kind);
- StringMap.bindings !vars
+ List.map make_param params
let transl_labels env closed lbls =
let all_labels = ref StringSet.empty in
@@ -214,11 +186,39 @@ let transl_constructor_arguments env closed ty_name c_name = function
Types.Cstr_record (id, lbls'),
Cstr_record lbls
+let make_constructor env type_path type_params c_name sargs sret_type =
+ let ty_name = Path.last type_path in
+ match sret_type with
+ | None ->
+ let args, targs =
+ transl_constructor_arguments env true ty_name c_name sargs
+ in
+ targs, None, args, None
+ | Some sret_type ->
+ (* if it's a generalized constructor we must first narrow and
+ then widen so as to not introduce any new constraints *)
+ let z = narrow () in
+ reset_type_variables ();
+ let args, targs =
+ transl_constructor_arguments env false ty_name c_name sargs
+ in
+ let tret_type = transl_simple_type env false sret_type in
+ let ret_type = tret_type.ctyp_type in
+ begin
+ match (Ctype.repr ret_type).desc with
+ Tconstr (p', _, _) when Path.same type_path p' -> ()
+ | _ -> raise (Error (sret_type.ptyp_loc, Constraint_failed
+ (ret_type, Ctype.newconstr type_path type_params)))
+ end;
+ widen z;
+ targs, Some tret_type, args, Some ret_type
+
let transl_declaration env sdecl id =
(* Bind type parameters *)
reset_type_variables();
Ctype.begin_def ();
- let params = make_params sdecl in
+ let tparams = make_params env sdecl.ptype_params in
+ let params = List.map (fun (cty, _) -> cty.ctyp_type) tparams in
let cstrs = List.map
(fun (sty, sty', loc) ->
transl_simple_type env false sty,
@@ -228,61 +228,44 @@ let transl_declaration env sdecl id =
let (tkind, kind) =
match sdecl.ptype_kind with
Ptype_abstract -> Ttype_abstract, Type_abstract
- | Ptype_variant cstrs ->
+ | Ptype_variant scstrs ->
let all_constrs = ref StringSet.empty in
List.iter
(fun {pcd_name = {txt = name}} ->
if StringSet.mem name !all_constrs then
raise(Error(sdecl.ptype_loc, Duplicate_constructor name));
all_constrs := StringSet.add name !all_constrs)
- cstrs;
+ scstrs;
if List.length
- (List.filter (fun cd -> cd.pcd_args <> Pcstr_tuple []) cstrs)
+ (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 {pcd_name = lid; pcd_args; pcd_res = ret_type; pcd_loc = loc; pcd_attributes = attrs} =
- let name = Ident.create lid.txt in
- match ret_type with
- | None ->
- let args =
- transl_constructor_arguments env true (Ident.name id) lid.txt
- pcd_args
- in
- (name, lid, args, None, None, loc, attrs)
- | Some sty ->
- (* if it's a generalized constructor we must first narrow and
- then widen so as to not introduce any new constraints *)
- let z = narrow () in
- reset_type_variables ();
- let args =
- transl_constructor_arguments env false (Ident.name id) lid.txt
- pcd_args
- in
- let cty = transl_simple_type env false sty in
- let ret_type =
- let ty = cty.ctyp_type in
- let p = Path.Pident id in
- match (Ctype.repr ty).desc with
- Tconstr (p', _, _) when Path.same p p' -> ty
- | _ ->
- raise (Error (sty.ptyp_loc, Constraint_failed
- (ty, Ctype.newconstr p params)))
- in
- widen z;
- (name, lid, args, Some cty, Some ret_type, loc, attrs)
+ let make_cstr scstr =
+ let name = Ident.create scstr.pcd_name.txt in
+ let targs, tret_type, args, ret_type =
+ make_constructor env (Path.Pident id) params
+ scstr.pcd_name.txt
+ scstr.pcd_args scstr.pcd_res
+ in
+ let tcstr =
+ { cd_id = name;
+ cd_name = scstr.pcd_name;
+ cd_args = targs;
+ cd_res = tret_type;
+ cd_loc = scstr.pcd_loc;
+ cd_attributes = scstr.pcd_attributes }
+ in
+ let cstr =
+ { Types.cd_id = name;
+ cd_args = args;
+ cd_res = ret_type;
+ cd_loc = scstr.pcd_loc;
+ cd_attributes = scstr.pcd_attributes }
+ in
+ tcstr, cstr
in
- let cstrs = List.map make_cstr cstrs in
- Ttype_variant (List.map (fun (name, lid, (_, args), res, _, loc, attrs) ->
- {cd_id = name; cd_name = lid; cd_args = args; cd_res = res;
- cd_loc = loc; cd_attributes = attrs}
- ) cstrs),
- Type_variant (List.map (fun (name, name_loc, (args, _), _, option, loc, attrs) ->
- {Types.cd_id = name; cd_args = args;
- cd_res = option;
- cd_loc = loc; cd_attributes = attrs;
- }
- ) cstrs)
-
+ let tcstrs, cstrs = List.split (List.map make_cstr scstrs) in
+ Ttype_variant tcstrs, Type_variant cstrs
| Ptype_record lbls ->
let lbls, lbls' = transl_labels env true lbls in
let rep =
@@ -291,6 +274,7 @@ let transl_declaration env sdecl id =
else Record_regular
in
Ttype_record lbls, Type_record(lbls', rep)
+ | Ptype_open -> Ttype_open, Type_open
in
let (tman, man) = match sdecl.ptype_manifest with
None -> None, None
@@ -336,7 +320,7 @@ let transl_declaration env sdecl id =
{
typ_id = id;
typ_name = sdecl.ptype_name;
- typ_params = sdecl.ptype_params;
+ typ_params = tparams;
typ_type = decl;
typ_cstrs = cstrs;
typ_loc = sdecl.ptype_loc;
@@ -402,7 +386,7 @@ let check_constraints env sdecl (_, decl) =
| Type_variant l ->
let find_pl = function
Ptype_variant pl -> pl
- | Ptype_record _ | Ptype_abstract -> assert false
+ | Ptype_record _ | Ptype_abstract | Ptype_open -> assert false
in
let pl = find_pl sdecl.ptype_kind in
let pl_index =
@@ -435,10 +419,11 @@ let check_constraints env sdecl (_, decl) =
| Type_record (l, _) ->
let find_pl = function
Ptype_record pl -> pl
- | Ptype_variant _ | Ptype_abstract -> assert false
+ | Ptype_variant _ | Ptype_abstract | Ptype_open -> assert false
in
let pl = find_pl sdecl.ptype_kind in
check_constraints_labels env visited l pl
+ | Type_open -> ()
end;
begin match decl.type_manifest with
| None -> ()
@@ -456,7 +441,8 @@ let check_constraints env sdecl (_, decl) =
*)
let check_coherence env loc id decl =
match decl with
- {type_kind = (Type_variant _ | Type_record _); type_manifest = Some ty} ->
+ { type_kind = (Type_variant _ | Type_record _| Type_open);
+ type_manifest = Some ty } ->
begin match (Ctype.repr ty).desc with
Tconstr(path, args, _) ->
begin try
@@ -659,15 +645,6 @@ 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 flags (v, i) =
- let (c, n) =
- match v with
- | Covariant -> (true, false)
- | Contravariant -> (false, true)
- | Invariant -> (true, true)
- in
- (c, n, i)
-
let compute_variance_type env check (required, loc) decl tyl =
(* Requirements *)
let required =
@@ -798,11 +775,17 @@ let compute_variance_gadt env check (required, loc as rloc) decl
(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, loc as rloc) =
- if decl.type_kind = Type_abstract && decl.type_manifest = None then
+ 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) (i (*|| decl.type_transparence = Type_new*)))
+ make (not n) (not c) (decl.type_kind <> Type_abstract || i))
required
else
let mn =
@@ -811,7 +794,7 @@ let compute_variance_decl env check decl (required, loc as rloc) =
| Some ty -> [false, ty]
in
match decl.type_kind with
- Type_abstract ->
+ 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
@@ -931,7 +914,8 @@ let check_duplicates sdecl_list =
("label", cname.txt, name', sdecl.ptype_name.txt))
with Not_found -> Hashtbl.add labels cname.txt sdecl.ptype_name.txt)
fl
- | Ptype_abstract -> ())
+ | Ptype_abstract -> ()
+ | Ptype_open -> ())
sdecl_list
(* Force recursion to go through id for private types*)
@@ -1069,105 +1053,234 @@ let transl_type_decl env sdecl_list =
(* Done *)
(final_decls, final_env)
-(* Translate an exception declaration *)
-let transl_closed_type env sty =
- let cty = transl_simple_type env true sty in
- let ty = cty.ctyp_type in
- let ty =
- match Ctype.free_variables ty with
- | [] -> ty
- | tv :: _ -> raise (Error (sty.ptyp_loc, Unbound_type_var_exc (tv, ty)))
+(* Translating type extensions *)
+
+let transl_extension_constructor env check_open type_path type_params
+ typext_params priv sext =
+ let id = Ident.create sext.pext_name.txt in
+ let rebind, args, ret_type, kind =
+ match sext.pext_kind with
+ Pext_decl(sargs, sret_type) ->
+ let targs, tret_type, args, ret_type =
+ make_constructor env type_path typext_params sext.pext_name.txt
+ sargs sret_type
+ in
+ None, args, ret_type, Text_decl(targs, tret_type)
+ | Pext_rebind lid ->
+ let cdescr = Typetexp.find_constructor env sext.pext_loc lid.txt in
+ let usage =
+ if cdescr.cstr_private = Private || priv = Public
+ then Env.Positive else Env.Privatize
+ in
+ Env.mark_constructor usage env (Longident.last lid.txt) cdescr;
+ let (args, cstr_res) = Ctype.instance_constructor cdescr in
+ let res, ret_type =
+ if cdescr.cstr_generalized then
+ let params = Ctype.instance_list env type_params in
+ let res = Ctype.newconstr type_path params in
+ let ret_type = Some (Ctype.newconstr type_path params) in
+ res, ret_type
+ else (Ctype.newconstr type_path typext_params), None
+ in
+ begin
+ try
+ Ctype.unify env cstr_res res
+ with Ctype.Unify trace ->
+ raise (Error(lid.loc,
+ Rebind_wrong_type(lid.txt, env, trace)))
+ end;
+ (* Remove "_" names from parameters used in the constructor *)
+ if not cdescr.cstr_generalized then begin
+ let vars =
+ Ctype.free_variables (Btype.newgenty (Ttuple args))
+ in
+ List.iter
+ (function {desc = Tvar (Some "_")} as ty ->
+ if List.memq ty vars then ty.desc <- Tvar None
+ | _ -> ())
+ typext_params
+ end;
+ (* Ensure that constructor's type matches the type being extended *)
+ let cstr_type_path, cstr_type_params =
+ match cdescr.cstr_res.desc with
+ Tconstr (p, _, _) ->
+ let decl = Env.find_type p env in
+ p, decl.type_params
+ | _ -> assert false
+ in
+ let cstr_types =
+ (Btype.newgenty
+ (Tconstr(cstr_type_path, cstr_type_params, ref Mnil)))
+ :: cstr_type_params
+ in
+ let ext_types =
+ (Btype.newgenty
+ (Tconstr(type_path, type_params, ref Mnil)))
+ :: type_params
+ in
+ if not (Ctype.equal env true cstr_types ext_types) then
+ raise (Error(lid.loc,
+ Rebind_mismatch(lid.txt, cstr_type_path, type_path)));
+ (* Disallow rebinding private constructors to non-private *)
+ begin
+ match cdescr.cstr_private, priv with
+ Private, Public ->
+ raise (Error(lid.loc, Rebind_private lid.txt))
+ | _ -> ()
+ end;
+ let path =
+ match cdescr.cstr_tag with
+ Cstr_extension(path, _) -> path
+ | _ -> assert false
+ in
+ let rebind, args =
+ if cdescr.cstr_inlined then
+ let p =
+ match cdescr.cstr_args with
+ | [ {desc=Tconstr(p, [], _)} ] -> p
+ | [ {desc=Tconstr(_, _, _)} ] ->
+ (* #5528: TODO *)
+ failwith "Rebinding of inlined extension constructors with free variables is not yet supported."
+ | _ -> assert false
+ in
+ let decl =
+ try Env.find_type p env with Not_found -> assert false
+ in
+ let lbls =
+ match decl.type_kind with Type_record (l, _) -> l | _ -> assert false
+ in
+ let id = Ident.create (Path.last type_path ^ "." ^ sext.pext_name.txt) in
+ Some p, Types.Cstr_record (id, lbls)
+ else
+ None, Types.Cstr_tuple args
+ in
+ rebind, args, ret_type, Text_rebind(path, lid)
in
- { cty with ctyp_type = ty }
-
-let transl_exception env excdecl =
- let loc = excdecl.pcd_loc in
- let id = Ident.create excdecl.pcd_name.txt in
- if excdecl.pcd_res <> None then
- raise (Error (loc, Exception_constructor_with_result));
+ let ext =
+ { ext_type_path = type_path;
+ ext_type_params = typext_params;
+ ext_args = args;
+ ext_ret_type = ret_type;
+ ext_private = priv;
+ Types.ext_loc = sext.pext_loc;
+ Types.ext_attributes = sext.pext_attributes; }
+ in
+ rebind,
+ { ext_id = id;
+ ext_name = sext.pext_name;
+ ext_type = ext;
+ ext_kind = kind;
+ Typedtree.ext_loc = sext.pext_loc;
+ Typedtree.ext_attributes = sext.pext_attributes; }
+
+let transl_type_extension check_open env loc styext =
reset_type_variables();
Ctype.begin_def();
- let exn_args, cd_args =
- transl_constructor_arguments env true "exn" excdecl.pcd_name.txt
- excdecl.pcd_args
- in
- Ctype.end_def();
- let cd =
- { cd_id = id;
- cd_name = excdecl.pcd_name;
- cd_args;
- cd_loc = loc;
- cd_res = None;
- cd_attributes = excdecl.pcd_attributes;
- }
+ let (type_path, type_decl) =
+ Typetexp.find_type env loc styext.ptyext_path.txt
in
- begin match exn_args with
- | Types.Cstr_tuple l -> List.iter Ctype.generalize l
- | Types.Cstr_record (_,l) ->
- List.iter (fun l -> Ctype.generalize l.Types.ld_type) l
+ begin
+ match type_decl.type_kind with
+ Type_open -> ()
+ | Type_abstract ->
+ if check_open then begin
+ try
+ let {pext_loc} =
+ List.find (function {pext_kind = Pext_decl _} -> true
+ | {pext_kind = Pext_rebind _} -> false)
+ styext.ptyext_constructors
+ in
+ raise (Error(pext_loc, Not_open_type type_path))
+ with Not_found -> ()
+ end
+ | _ -> raise (Error(loc, Not_extensible_type type_path))
end;
- let exn_decl =
- {
- exn_args;
- exn_attributes = excdecl.pcd_attributes;
- Types.exn_loc = loc;
- }
- in
- let newenv = Env.add_exception ~check:true id exn_decl env in
- cd, exn_decl, newenv
-
-(* Translate an exception rebinding *)
-let transl_exn_rebind env ser =
- let name = ser.pexrb_name in
- let lid = ser.pexrb_lid in
- let cdescr =
- try
- Env.lookup_constructor lid.txt env
- with Not_found ->
- raise(Error(lid.loc, Unbound_exception lid.txt)) in
- Env.mark_constructor Env.Positive env (Longident.last lid.txt) cdescr;
- let path =
- match cdescr.cstr_tag with
- Cstr_exception (path, _) -> path
- | _ -> raise(Error(lid.loc, Not_an_exception lid.txt))
+ let type_variance =
+ List.map (fun v ->
+ let (co, cn) = Variance.get_upper v in
+ (not cn, not co, false))
+ type_decl.type_variance
in
- let exn_args, rebind =
- if cdescr.cstr_inlined then
- let p =
- match cdescr.cstr_args with
- | [ {desc=Tconstr(p, [], _)} ] -> p
- | _ -> assert false
- in
- let decl =
- try Env.find_type p env with Not_found -> assert false
- in
- let lbls =
- match decl.type_kind with Type_record (l, _) -> l | _ -> assert false
- in
- let id = Ident.create ("exn." ^ name.txt) in
- Types.Cstr_record (id, lbls), Some p
+ let err =
+ if type_decl.type_arity <> List.length styext.ptyext_params then
+ [Includecore.Arity]
else
- Types.Cstr_tuple cdescr.cstr_args, None
+ 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]
in
- let exn_decl =
- {
- exn_args = exn_args;
- exn_attributes = [];
- Types.exn_loc = ser.pexrb_loc;
- }
+ if err <> [] then
+ raise (Error(loc, Extension_mismatch (type_path, err)));
+ 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)
+ (Ctype.instance_list env type_decl.type_params)
+ type_params;
+ let rebind_constructors =
+ List.map (transl_extension_constructor env check_open type_path
+ type_decl.type_params type_params styext.ptyext_private)
+ styext.ptyext_constructors
in
- let (id, newenv) = Env.enter_exception ?rebind name.txt exn_decl env in
- let er =
- { exrb_id = id;
- exrb_name = name;
- exrb_path = path;
- exrb_txt = lid;
- exrb_type = exn_decl;
- exrb_attributes = ser.pexrb_attributes;
- exrb_loc = ser.pexrb_loc;
- }
+ let constructors = List.map snd rebind_constructors in
+ Ctype.end_def();
+ (* Generalize types *)
+ List.iter Ctype.generalize type_params;
+ List.iter
+ (fun ext ->
+ Btype.iter_type_expr_cstr_args Ctype.generalize ext.ext_type.ext_args;
+ may Ctype.generalize ext.ext_type.ext_ret_type)
+ constructors;
+ (* Check that all type variable are closed *)
+ List.iter
+ (fun ext ->
+ match Ctype.closed_extension_constructor ext.ext_type with
+ Some ty -> raise(Error(ext.ext_loc, Unbound_type_var_ext(ty, ext.ext_type)))
+ | None -> ())
+ constructors;
+ (* Check variances are correct *)
+ List.iter
+ (fun ext ->
+ ignore (compute_variance_extension env true type_decl
+ ext.ext_type (type_variance, loc)))
+ constructors;
+ (* Add extension constructors to the environment *)
+ let newenv =
+ List.fold_left
+ (fun env (rebind, ext) ->
+ Env.add_extension ?rebind ~check:true ext.ext_id ext.ext_type env)
+ env rebind_constructors
+ in
+ let tyext =
+ { tyext_path = type_path;
+ tyext_txt = styext.ptyext_path;
+ tyext_params = ttype_params;
+ tyext_constructors = constructors;
+ tyext_private = styext.ptyext_private;
+ tyext_attributes = styext.ptyext_attributes; }
in
- er, newenv
+ (tyext, newenv)
+
+let transl_exception env sext =
+ reset_type_variables();
+ Ctype.begin_def();
+ let rebind, ext =
+ transl_extension_constructor env false
+ Predef.path_exn [] [] Asttypes.Public sext
+ in
+ Ctype.end_def();
+ (* Generalize types *)
+ Btype.iter_type_expr_cstr_args Ctype.generalize ext.ext_type.ext_args;
+ may Ctype.generalize ext.ext_type.ext_ret_type;
+ (* Check that all type variable are closed *)
+ begin match Ctype.closed_extension_constructor ext.ext_type with
+ Some ty ->
+ raise (Error(ext.ext_loc, Unbound_type_var_ext(ty, ext.ext_type)))
+ | None -> ()
+ end;
+ let newenv = Env.add_extension ?rebind ~check:true ext.ext_id ext.ext_type env in
+ ext, newenv
(* Translate a value declaration *)
let transl_value_decl env loc valdecl =
@@ -1212,7 +1325,8 @@ let transl_with_constraint env id row_path orig_decl sdecl =
Env.mark_type_used (Ident.name id) orig_decl;
reset_type_variables();
Ctype.begin_def();
- let params = make_params sdecl in
+ let tparams = make_params env sdecl.ptype_params in
+ let params = List.map (fun (cty, _) -> cty.ctyp_type) tparams in
let orig_decl = Ctype.instance_declaration orig_decl in
let arity_ok = List.length params = orig_decl.type_arity in
if arity_ok then
@@ -1275,7 +1389,7 @@ let transl_with_constraint env id row_path orig_decl sdecl =
{
typ_id = id;
typ_name = sdecl.ptype_name;
- typ_params = sdecl.ptype_params;
+ typ_params = tparams;
typ_type = decl;
typ_cstrs = constraints;
typ_loc = sdecl.ptype_loc;
@@ -1418,7 +1532,7 @@ let report_error ppf = function
match c.cd_args with
| Cstr_tuple tl ->
Btype.newgenty (Ttuple tl)
- | Cstr_record _ -> assert false
+ | Cstr_record _ -> assert false (* #5528: TODO *)
)
"case" (fun c -> Ident.name c.Types.cd_id ^ " of ")
| Type_record (tl, _), _ ->
@@ -1428,14 +1542,48 @@ let report_error ppf = function
explain_unbound_single ppf ty ty'
| _ -> ()
end
- | Unbound_type_var_exc (tv, ty) ->
- fprintf ppf "A type variable is unbound in this exception declaration";
- explain_unbound_single ppf (Ctype.repr tv) ty
- | Unbound_exception lid ->
- fprintf ppf "Unbound exception constructor %a" Printtyp.longident lid
- | Not_an_exception lid ->
- fprintf ppf "The constructor %a is not an exception"
+ | Unbound_type_var_ext (ty, ext) ->
+ fprintf ppf "A type variable is unbound in this extension constructor";
+ let args = match ext.ext_args with
+ | Cstr_tuple l -> l
+ | Cstr_record _ -> assert false (* #5528: TODO *)
+ in
+ explain_unbound ppf ty args (fun c -> c) "type" (fun _ -> "")
+ | Not_open_type path ->
+ fprintf ppf "@[%s@ %a@]"
+ "Cannot extend type definition"
+ Printtyp.path path
+ | Not_extensible_type path ->
+ fprintf ppf "@[%s@ %a@ %s@]"
+ "Type"
+ Printtyp.path path
+ "is not extensible"
+ | Extension_mismatch (path, errs) ->
+ fprintf ppf "@[<v>@[<hov>%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
+ | Rebind_wrong_type (lid, env, trace) ->
+ Printtyp.report_unification_error ppf env trace
+ (function ppf ->
+ fprintf ppf "The constructor %a@ has type"
+ Printtyp.longident lid)
+ (function ppf ->
+ fprintf ppf "but was expected to be of type")
+ | Rebind_mismatch (lid, p, p') ->
+ fprintf ppf
+ "@[%s@ %a@ %s@ %s@ %s@ %s@ %s@]"
+ "The constructor" Printtyp.longident lid
+ "extends type" (Path.name p)
+ "whose declaration does not match"
+ "the declaration of type" (Path.name p')
+ | Rebind_private lid ->
+ fprintf ppf "@[%s@ %a@ %s@]"
+ "The constructor"
Printtyp.longident lid
+ "is private"
| Bad_variance (n, v1, v2) ->
let variance (p,n,i) =
let inj = if i then "injective " else "" in
@@ -1481,8 +1629,6 @@ let report_error ppf = function
fprintf ppf "@[%s@ %s@ %s@]"
"In this GADT definition," "the variance of some parameter"
"cannot be checked"
- | Exception_constructor_with_result ->
- fprintf ppf "Exception constructors cannot specify a result type"
let () =
Location.register_error_of_exn
diff --git a/typing/typedecl.mli b/typing/typedecl.mli
index bfd186d26c..bb3e3ea583 100644
--- a/typing/typedecl.mli
+++ b/typing/typedecl.mli
@@ -21,11 +21,11 @@ val transl_type_decl:
val transl_exception:
Env.t ->
- Parsetree.constructor_declaration ->
- Typedtree.constructor_declaration * exception_declaration * Env.t
+ Parsetree.extension_constructor -> Typedtree.extension_constructor * Env.t
-val transl_exn_rebind:
- Env.t -> Parsetree.exception_rebind -> Typedtree.exception_rebind * Env.t
+val transl_type_extension:
+ bool -> Env.t -> Location.t -> Parsetree.type_extension ->
+ Typedtree.type_extension * Env.t
val transl_value_decl:
Env.t -> Location.t ->
@@ -70,14 +70,17 @@ type error =
| Null_arity_external
| Missing_native_external
| Unbound_type_var of type_expr * type_declaration
- | Unbound_exception of Longident.t
- | Not_an_exception of Longident.t
+ | Not_open_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
+ | Rebind_mismatch of Longident.t * Path.t * Path.t
+ | Rebind_private of Longident.t
| Bad_variance of int * (bool*bool*bool) * (bool*bool*bool)
| Unavailable_type_constructor of Path.t
| Bad_fixed_type of string
- | Unbound_type_var_exc of type_expr * type_expr
+ | Unbound_type_var_ext of type_expr * extension_constructor
| Varying_anonymous
- | Exception_constructor_with_result
exception Error of Location.t * error
diff --git a/typing/typedtree.ml b/typing/typedtree.ml
index 1c41187860..52067415cc 100644
--- a/typing/typedtree.ml
+++ b/typing/typedtree.ml
@@ -76,7 +76,7 @@ and expression_desc =
| Texp_let of rec_flag * value_binding list * expression
| Texp_function of label * case list * partial
| Texp_apply of expression * (label * expression option * optional) list
- | Texp_match of expression * case list * partial
+ | Texp_match of expression * case list * case list * partial
| Texp_try of expression * case list
| Texp_tuple of expression list
| Texp_construct of
@@ -169,6 +169,7 @@ and class_field_desc =
| Tcf_method of string loc * private_flag * class_field_kind
| Tcf_constraint of core_type * core_type
| Tcf_initializer of expression
+ | Tcf_attribute of attribute
(* Value expressions for the module language *)
@@ -210,8 +211,8 @@ and structure_item_desc =
| Tstr_value of rec_flag * value_binding list
| Tstr_primitive of value_description
| Tstr_type of type_declaration list
- | Tstr_exception of constructor_declaration
- | Tstr_exn_rebind of exception_rebind
+ | Tstr_typext of type_extension
+ | Tstr_exception of extension_constructor
| Tstr_module of module_binding
| Tstr_recmodule of module_binding list
| Tstr_modtype of module_type_declaration
@@ -276,7 +277,8 @@ and signature_item =
and signature_item_desc =
Tsig_value of value_description
| Tsig_type of type_declaration list
- | Tsig_exception of constructor_declaration
+ | Tsig_typext of type_extension
+ | Tsig_exception of extension_constructor
| Tsig_module of module_declaration
| Tsig_recmodule of module_declaration list
| Tsig_modtype of module_type_declaration
@@ -346,7 +348,7 @@ and core_type_desc =
| Ttyp_arrow of label * core_type * core_type
| Ttyp_tuple of core_type list
| Ttyp_constr of Path.t * Longident.t loc * core_type list
- | Ttyp_object of (string * core_type) list * closed_flag
+ | Ttyp_object of (string * attributes * core_type) list * closed_flag
| Ttyp_class of Path.t * Longident.t loc * core_type list
| Ttyp_alias of core_type * string
| Ttyp_variant of row_field list * closed_flag * label list option
@@ -354,14 +356,14 @@ and core_type_desc =
| Ttyp_package of package_type
and package_type = {
- pack_name : Path.t;
+ pack_path : Path.t;
pack_fields : (Longident.t loc * core_type) list;
pack_type : Types.module_type;
pack_txt : Longident.t loc;
}
and row_field =
- Ttag of label * bool * core_type list
+ Ttag of label * attributes * bool * core_type list
| Tinherit of core_type
and value_description =
@@ -377,7 +379,7 @@ and value_description =
and type_declaration =
{ typ_id: Ident.t;
typ_name: string loc;
- typ_params: (string loc option * variance) list;
+ typ_params: (core_type * variance) list;
typ_type: Types.type_declaration;
typ_cstrs: (core_type * core_type * Location.t) list;
typ_kind: type_kind;
@@ -391,6 +393,7 @@ and type_kind =
Ttype_abstract
| Ttype_variant of constructor_declaration list
| Ttype_record of label_declaration list
+ | Ttype_open
and label_declaration =
{
@@ -416,16 +419,29 @@ and constructor_arguments =
| Cstr_tuple of core_type list
| Cstr_record of label_declaration list
-and exception_rebind =
- {
- exrb_id: Ident.t;
- exrb_name: string loc;
- exrb_path: Path.t;
- exrb_txt: Longident.t loc;
- exrb_type: Types.exception_declaration;
- exrb_loc: Location.t;
- exrb_attributes: attribute list;
- }
+and type_extension =
+ {
+ tyext_path: Path.t;
+ tyext_txt: Longident.t loc;
+ tyext_params: (core_type * variance) list;
+ tyext_constructors: extension_constructor list;
+ tyext_private: private_flag;
+ tyext_attributes: attribute list;
+ }
+
+and extension_constructor =
+ {
+ ext_id: Ident.t;
+ ext_name: string loc;
+ ext_type : Types.extension_constructor;
+ ext_kind : extension_constructor_kind;
+ ext_loc : Location.t;
+ ext_attributes: attribute list;
+ }
+
+and extension_constructor_kind =
+ Text_decl of constructor_arguments * core_type option
+ | Text_rebind of Path.t * Longident.t loc
and class_type =
{
@@ -458,6 +474,7 @@ and class_type_field_desc =
| Tctf_val of (string * mutable_flag * virtual_flag * core_type)
| Tctf_method of (string * private_flag * virtual_flag * core_type)
| Tctf_constraint of (core_type * core_type)
+ | Tctf_attribute of attribute
and class_declaration =
class_expr class_infos
@@ -470,7 +487,7 @@ and class_type_declaration =
and 'a class_infos =
{ ci_virt: virtual_flag;
- ci_params: (string loc * variance) list;
+ ci_params: (core_type * variance) list;
ci_id_name : string loc;
ci_id_class: Ident.t;
ci_id_class_type : Ident.t;
diff --git a/typing/typedtree.mli b/typing/typedtree.mli
index c077c92862..fa36dac8c4 100644
--- a/typing/typedtree.mli
+++ b/typing/typedtree.mli
@@ -75,7 +75,7 @@ and expression_desc =
| Texp_let of rec_flag * value_binding list * expression
| Texp_function of label * case list * partial
| Texp_apply of expression * (label * expression option * optional) list
- | Texp_match of expression * case list * partial
+ | Texp_match of expression * case list * case list * partial
| Texp_try of expression * case list
| Texp_tuple of expression list
| Texp_construct of
@@ -168,6 +168,7 @@ and class_field_desc =
| Tcf_method of string loc * private_flag * class_field_kind
| Tcf_constraint of core_type * core_type
| Tcf_initializer of expression
+ | Tcf_attribute of attribute
(* Value expressions for the module language *)
@@ -209,8 +210,8 @@ and structure_item_desc =
| Tstr_value of rec_flag * value_binding list
| Tstr_primitive of value_description
| Tstr_type of type_declaration list
- | Tstr_exception of constructor_declaration
- | Tstr_exn_rebind of exception_rebind
+ | Tstr_typext of type_extension
+ | Tstr_exception of extension_constructor
| Tstr_module of module_binding
| Tstr_recmodule of module_binding list
| Tstr_modtype of module_type_declaration
@@ -275,7 +276,8 @@ and signature_item =
and signature_item_desc =
Tsig_value of value_description
| Tsig_type of type_declaration list
- | Tsig_exception of constructor_declaration
+ | Tsig_typext of type_extension
+ | Tsig_exception of extension_constructor
| Tsig_module of module_declaration
| Tsig_recmodule of module_declaration list
| Tsig_modtype of module_type_declaration
@@ -345,7 +347,7 @@ and core_type_desc =
| Ttyp_arrow of label * core_type * core_type
| Ttyp_tuple of core_type list
| Ttyp_constr of Path.t * Longident.t loc * core_type list
- | Ttyp_object of (string * core_type) list * closed_flag
+ | Ttyp_object of (string * attributes * core_type) list * closed_flag
| Ttyp_class of Path.t * Longident.t loc * core_type list
| Ttyp_alias of core_type * string
| Ttyp_variant of row_field list * closed_flag * label list option
@@ -353,14 +355,14 @@ and core_type_desc =
| Ttyp_package of package_type
and package_type = {
- pack_name : Path.t;
+ pack_path : Path.t;
pack_fields : (Longident.t loc * core_type) list;
pack_type : Types.module_type;
pack_txt : Longident.t loc;
}
and row_field =
- Ttag of label * bool * core_type list
+ Ttag of label * attributes * bool * core_type list
| Tinherit of core_type
and value_description =
@@ -377,7 +379,7 @@ and type_declaration =
{
typ_id: Ident.t;
typ_name: string loc;
- typ_params: (string loc option * variance) list;
+ typ_params: (core_type * variance) list;
typ_type: Types.type_declaration;
typ_cstrs: (core_type * core_type * Location.t) list;
typ_kind: type_kind;
@@ -391,6 +393,7 @@ and type_kind =
Ttype_abstract
| Ttype_variant of constructor_declaration list
| Ttype_record of label_declaration list
+ | Ttype_open
and label_declaration =
{
@@ -416,16 +419,29 @@ and constructor_arguments =
| Cstr_tuple of core_type list
| Cstr_record of label_declaration list
-and exception_rebind =
- {
- exrb_id: Ident.t;
- exrb_name: string loc;
- exrb_path: Path.t;
- exrb_txt: Longident.t loc;
- exrb_type: Types.exception_declaration;
- exrb_loc: Location.t;
- exrb_attributes: attribute list;
- }
+and type_extension =
+ {
+ tyext_path: Path.t;
+ tyext_txt: Longident.t loc;
+ tyext_params: (core_type * variance) list;
+ tyext_constructors: extension_constructor list;
+ tyext_private: private_flag;
+ tyext_attributes: attributes;
+ }
+
+and extension_constructor =
+ {
+ ext_id: Ident.t;
+ ext_name: string loc;
+ ext_type : Types.extension_constructor;
+ ext_kind : extension_constructor_kind;
+ ext_loc : Location.t;
+ ext_attributes: attributes;
+ }
+
+and extension_constructor_kind =
+ Text_decl of constructor_arguments * core_type option
+ | Text_rebind of Path.t * Longident.t loc
and class_type =
{
@@ -458,6 +474,7 @@ and class_type_field_desc =
| Tctf_val of (string * mutable_flag * virtual_flag * core_type)
| Tctf_method of (string * private_flag * virtual_flag * core_type)
| Tctf_constraint of (core_type * core_type)
+ | Tctf_attribute of attribute
and class_declaration =
class_expr class_infos
@@ -470,7 +487,7 @@ and class_type_declaration =
and 'a class_infos =
{ ci_virt: virtual_flag;
- ci_params: (string loc * variance) list;
+ ci_params: (core_type * variance) list;
ci_id_name : string loc;
ci_id_class: Ident.t;
ci_id_class_type : Ident.t;
diff --git a/typing/typedtreeIter.ml b/typing/typedtreeIter.ml
index b5279fe273..28026b5987 100644
--- a/typing/typedtreeIter.ml
+++ b/typing/typedtreeIter.ml
@@ -24,6 +24,8 @@ module type IteratorArgument = sig
val enter_structure : structure -> unit
val enter_value_description : value_description -> unit
val enter_type_declaration : type_declaration -> unit
+ val enter_type_extension : type_extension -> unit
+ val enter_extension_constructor : extension_constructor -> unit
val enter_pattern : pattern -> unit
val enter_expression : expression -> unit
val enter_package_type : package_type -> unit
@@ -49,6 +51,8 @@ module type IteratorArgument = sig
val leave_structure : structure -> unit
val leave_value_description : value_description -> unit
val leave_type_declaration : type_declaration -> unit
+ val leave_type_extension : type_extension -> unit
+ val leave_extension_constructor : extension_constructor -> unit
val leave_pattern : pattern -> unit
val leave_expression : expression -> unit
val leave_package_type : package_type -> unit
@@ -130,24 +134,18 @@ module MakeIterator(Iter : IteratorArgument) : sig
iter_bindings rec_flag list
| Tstr_primitive vd -> iter_value_description vd
| Tstr_type list -> List.iter iter_type_declaration list
- | Tstr_exception cd -> iter_constructor_declaration cd
- | Tstr_exn_rebind _ -> ()
+ | Tstr_typext tyext -> iter_type_extension tyext
+ | Tstr_exception ext -> iter_extension_constructor 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_class list ->
- List.iter (fun (ci, _, _) ->
- Iter.enter_class_declaration ci;
- iter_class_expr ci.ci_expr;
- Iter.leave_class_declaration ci;
- ) list
+ List.iter (fun (ci, _, _) -> iter_class_declaration ci) list
| Tstr_class_type list ->
- List.iter (fun (id, _, ct) ->
- Iter.enter_class_type_declaration ct;
- iter_class_type ct.ci_expr;
- Iter.leave_class_type_declaration ct;
- ) list
+ List.iter
+ (fun (id, _, ct) -> iter_class_type_declaration ct)
+ list
| Tstr_include incl -> iter_module_expr incl.incl_mod
| Tstr_attribute _ ->
()
@@ -162,15 +160,20 @@ module MakeIterator(Iter : IteratorArgument) : sig
iter_core_type v.val_desc;
Iter.leave_value_description v
- and iter_constructor_declaration cd =
- begin match cd.cd_args with
+ and iter_constructor_arguments = function
| Cstr_tuple l -> List.iter iter_core_type l
| Cstr_record l -> List.iter (fun ld -> iter_core_type ld.ld_type) l
- end;
+
+ and iter_constructor_declaration cd =
+ iter_constructor_arguments cd.cd_args;
option iter_core_type cd.cd_res;
+ and iter_type_parameter (ct, v) =
+ iter_core_type ct
+
and iter_type_declaration decl =
Iter.enter_type_declaration decl;
+ List.iter iter_type_parameter decl.typ_params;
List.iter (fun (ct1, ct2, loc) ->
iter_core_type ct1;
iter_core_type ct2
@@ -184,13 +187,27 @@ module MakeIterator(Iter : IteratorArgument) : sig
(fun ld ->
iter_core_type ld.ld_type
) list
+ | Ttype_open -> ()
end;
- begin match decl.typ_manifest with
- None -> ()
- | Some ct -> iter_core_type ct
- end;
+ option iter_core_type decl.typ_manifest;
Iter.leave_type_declaration decl
+ and iter_extension_constructor ext =
+ Iter.enter_extension_constructor ext;
+ begin match ext.ext_kind with
+ Text_decl(args, ret) ->
+ iter_constructor_arguments args;
+ option iter_core_type ret
+ | Text_rebind _ -> ()
+ end;
+ Iter.leave_extension_constructor ext;
+
+ and iter_type_extension tyext =
+ Iter.enter_type_extension tyext;
+ List.iter iter_type_parameter tyext.tyext_params;
+ List.iter iter_extension_constructor tyext.tyext_constructors;
+ Iter.leave_type_extension tyext
+
and iter_pattern pat =
Iter.enter_pattern pat;
List.iter (fun (cstr, _, _attrs) -> match cstr with
@@ -250,9 +267,10 @@ module MakeIterator(Iter : IteratorArgument) : sig
None -> ()
| Some exp -> iter_expression exp
) list
- | Texp_match (exp, list, _) ->
+ | Texp_match (exp, list1, list2, _) ->
iter_expression exp;
- iter_cases list
+ iter_cases list1;
+ iter_cases list2;
| Texp_try (exp, list) ->
iter_expression exp;
iter_cases list
@@ -340,8 +358,10 @@ module MakeIterator(Iter : IteratorArgument) : sig
iter_value_description vd
| Tsig_type list ->
List.iter iter_type_declaration list
- | Tsig_exception cd ->
- iter_constructor_declaration cd
+ | Tsig_exception ext ->
+ iter_extension_constructor ext
+ | Tsig_typext tyext ->
+ iter_type_extension tyext
| Tsig_module md ->
iter_module_type md.md_type
| Tsig_recmodule list ->
@@ -367,16 +387,23 @@ module MakeIterator(Iter : IteratorArgument) : sig
end;
Iter.leave_module_type_declaration mtd
+ and iter_class_declaration cd =
+ Iter.enter_class_declaration cd;
+ List.iter iter_type_parameter cd.ci_params;
+ iter_class_expr cd.ci_expr;
+ Iter.leave_class_declaration cd;
and iter_class_description cd =
Iter.enter_class_description cd;
+ List.iter iter_type_parameter cd.ci_params;
iter_class_type cd.ci_expr;
Iter.leave_class_description cd;
and iter_class_type_declaration cd =
Iter.enter_class_type_declaration cd;
+ List.iter iter_type_parameter cd.ci_params;
iter_class_type cd.ci_expr;
- Iter.leave_class_type_declaration cd;
+ Iter.leave_class_type_declaration cd;
and iter_module_type mty =
Iter.enter_module_type mty;
@@ -497,6 +524,7 @@ module MakeIterator(Iter : IteratorArgument) : sig
| Tctf_constraint (ct1, ct2) ->
iter_core_type ct1;
iter_core_type ct2
+ | Tctf_attribute _ -> ()
end;
Iter.leave_class_type_field ctf
@@ -513,7 +541,7 @@ module MakeIterator(Iter : IteratorArgument) : sig
| Ttyp_constr (path, _, list) ->
List.iter iter_core_type list
| Ttyp_object (list, o) ->
- List.iter (fun (_, t) -> iter_core_type t) list
+ List.iter (fun (_, _, t) -> iter_core_type t) list
| Ttyp_class (path, _, list) ->
List.iter iter_core_type list
| Ttyp_alias (ct, s) ->
@@ -534,7 +562,7 @@ module MakeIterator(Iter : IteratorArgument) : sig
and iter_row_field rf =
match rf with
- Ttag (label, bool, list) ->
+ Ttag (label, _attrs, bool, list) ->
List.iter iter_core_type list
| Tinherit ct -> iter_core_type ct
@@ -557,6 +585,7 @@ module MakeIterator(Iter : IteratorArgument) : sig
iter_expression exp
| Tcf_initializer exp ->
iter_expression exp
+ | Tcf_attribute _ -> ()
end;
Iter.leave_class_field cf;
end
@@ -566,7 +595,8 @@ module DefaultIteratorArgument = struct
let enter_structure _ = ()
let enter_value_description _ = ()
let enter_type_declaration _ = ()
- let enter_exception_declaration _ = ()
+ let enter_type_extension _ = ()
+ let enter_extension_constructor _ = ()
let enter_pattern _ = ()
let enter_expression _ = ()
let enter_package_type _ = ()
@@ -593,7 +623,8 @@ module DefaultIteratorArgument = struct
let leave_structure _ = ()
let leave_value_description _ = ()
let leave_type_declaration _ = ()
- let leave_exception_declaration _ = ()
+ let leave_type_extension _ = ()
+ let leave_extension_constructor _ = ()
let leave_pattern _ = ()
let leave_expression _ = ()
let leave_package_type _ = ()
diff --git a/typing/typedtreeIter.mli b/typing/typedtreeIter.mli
index 1582929803..547fc5c34b 100644
--- a/typing/typedtreeIter.mli
+++ b/typing/typedtreeIter.mli
@@ -18,6 +18,8 @@ module type IteratorArgument = sig
val enter_structure : structure -> unit
val enter_value_description : value_description -> unit
val enter_type_declaration : type_declaration -> unit
+ val enter_type_extension : type_extension -> unit
+ val enter_extension_constructor : extension_constructor -> unit
val enter_pattern : pattern -> unit
val enter_expression : expression -> unit
val enter_package_type : package_type -> unit
@@ -43,6 +45,8 @@ module type IteratorArgument = sig
val leave_structure : structure -> unit
val leave_value_description : value_description -> unit
val leave_type_declaration : type_declaration -> unit
+ val leave_type_extension : type_extension -> unit
+ val leave_extension_constructor : extension_constructor -> unit
val leave_pattern : pattern -> unit
val leave_expression : expression -> unit
val leave_package_type : package_type -> unit
diff --git a/typing/typedtreeMap.ml b/typing/typedtreeMap.ml
index c9da597c62..6b28cc8503 100644
--- a/typing/typedtreeMap.ml
+++ b/typing/typedtreeMap.ml
@@ -16,6 +16,9 @@ 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
@@ -27,10 +30,10 @@ module type MapArgument = sig
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_infos : 'a class_infos -> 'a class_infos
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
@@ -41,6 +44,9 @@ module type MapArgument = sig
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
@@ -52,10 +58,10 @@ module type MapArgument = sig
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_infos : 'a class_infos -> 'a class_infos
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
@@ -113,10 +119,10 @@ module MakeMap(Map : MapArgument) = struct
Tstr_primitive (map_value_description vd)
| Tstr_type list ->
Tstr_type (List.map map_type_declaration list)
- | Tstr_exception cd ->
- Tstr_exception (map_constructor_declaration cd)
- | Tstr_exn_rebind er ->
- Tstr_exn_rebind er
+ | 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 ->
@@ -127,21 +133,20 @@ module MakeMap(Map : MapArgument) = struct
| Tstr_open od -> Tstr_open od
| Tstr_class list ->
let list =
- List.map (fun (ci, string_list, virtual_flag) ->
- let ci = Map.enter_class_infos ci in
- let ci_expr = map_class_expr ci.ci_expr in
- (Map.leave_class_infos { ci with ci_expr = ci_expr},
- string_list, virtual_flag)
- ) list
+ List.map
+ (fun (ci, string_list, virtual_flag) ->
+ map_class_declaration ci, string_list, virtual_flag)
+ list
in
- Tstr_class list
+ Tstr_class list
| Tstr_class_type list ->
- let list = List.map (fun (id, name, ct) ->
- let ct = Map.enter_class_infos ct in
- let ci_expr = map_class_type ct.ci_expr in
- (id, name, Map.leave_class_infos { ct with ci_expr = ci_expr})
- ) list in
- 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
@@ -158,6 +163,7 @@ module MakeMap(Map : MapArgument) = struct
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,
@@ -176,29 +182,48 @@ module MakeMap(Map : MapArgument) = struct
) list
in
Ttype_record list
+ | Ttype_open -> Ttype_open
in
- let typ_manifest =
- match decl.typ_manifest with
- None -> None
- | Some ct -> Some (map_core_type ct)
- in
- Map.leave_type_declaration { decl with typ_cstrs = typ_cstrs;
- typ_kind = typ_kind; typ_manifest = typ_manifest }
+ 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 =
- match cd.cd_args with
- | 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)
- in
+ 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 =
@@ -258,10 +283,11 @@ module MakeMap(Map : MapArgument) = struct
in
(label, expo, optional)
) list )
- | Texp_match (exp, list, partial) ->
+ | Texp_match (exp, list1, list2, partial) ->
Texp_match (
map_expression exp,
- map_cases list,
+ map_cases list1,
+ map_cases list2,
partial
)
| Texp_try (exp, list) ->
@@ -392,8 +418,10 @@ module MakeMap(Map : MapArgument) = struct
Tsig_value vd ->
Tsig_value (map_value_description vd)
| Tsig_type list -> Tsig_type (List.map map_type_declaration list)
- | Tsig_exception cd ->
- Tsig_exception (map_constructor_declaration cd)
+ | 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 ->
@@ -419,16 +447,26 @@ module MakeMap(Map : MapArgument) = struct
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_expr = ci_expr}
+ 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_expr = ci_expr }
+ 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
@@ -551,6 +589,7 @@ module MakeMap(Map : MapArgument) = struct
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 }
@@ -566,7 +605,8 @@ module MakeMap(Map : MapArgument) = struct
| Ttyp_constr (path, lid, list) ->
Ttyp_constr (path, lid, List.map map_core_type list)
| Ttyp_object (list, o) ->
- Ttyp_object (List.map (fun (s, t) -> (s, map_core_type t)) list, o)
+ Ttyp_object
+ (List.map (fun (s, a, t) -> (s, a, map_core_type t)) 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)
@@ -585,8 +625,8 @@ module MakeMap(Map : MapArgument) = struct
and map_row_field rf =
match rf with
- Ttag (label, bool, list) ->
- Ttag (label, bool, List.map map_core_type list)
+ Ttag (label, attrs, bool, list) ->
+ Ttag (label, attrs, bool, List.map map_core_type list)
| Tinherit ct -> Tinherit (map_core_type ct)
and map_class_field cf =
@@ -606,6 +646,7 @@ module MakeMap(Map : MapArgument) = struct
| 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
@@ -616,7 +657,8 @@ module DefaultMapArgument = struct
let enter_structure t = t
let enter_value_description t = t
let enter_type_declaration t = t
- let enter_exception_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
@@ -628,9 +670,9 @@ module DefaultMapArgument = struct
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_infos t = t
let enter_class_type t = t
let enter_class_type_field t = t
let enter_core_type t = t
@@ -642,7 +684,8 @@ module DefaultMapArgument = struct
let leave_structure t = t
let leave_value_description t = t
let leave_type_declaration t = t
- let leave_exception_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
@@ -654,9 +697,9 @@ module DefaultMapArgument = struct
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_infos t = t
let leave_class_type t = t
let leave_class_type_field t = t
let leave_core_type t = t
diff --git a/typing/typedtreeMap.mli b/typing/typedtreeMap.mli
index 9ee2c8c4a5..5178a51800 100644
--- a/typing/typedtreeMap.mli
+++ b/typing/typedtreeMap.mli
@@ -16,6 +16,9 @@ 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
@@ -27,10 +30,10 @@ module type MapArgument = sig
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_infos : 'a class_infos -> 'a class_infos
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
@@ -41,6 +44,9 @@ module type MapArgument = sig
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
@@ -52,10 +58,10 @@ module type MapArgument = sig
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_infos : 'a class_infos -> 'a class_infos
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
diff --git a/typing/typemod.ml b/typing/typemod.ml
index 418af07f6a..11aeab9321 100644
--- a/typing/typemod.ml
+++ b/typing/typemod.ml
@@ -37,11 +37,11 @@ type error =
| Not_a_packed_module of type_expr
| Incomplete_packed_module of type_expr
| Scoping_pack of Longident.t * type_expr
- | Extension of string
| Recursive_module_require_explicit_type
| Apply_generative
exception Error of Location.t * Env.t * error
+exception Error_forward of Location.error
open Typedtree
@@ -68,8 +68,7 @@ let extract_sig_open env loc mty =
(* Compute the environment after opening a module *)
let type_open_ ?toplevel ovf env loc lid =
- let path = Typetexp.find_module env lid.loc lid.txt in
- let md = Env.find_module path env in
+ let path, md = Typetexp.find_module env lid.loc lid.txt in
let sg = extract_sig_open env lid.loc md.md_type in
path, Env.open_signature ~loc ?toplevel ovf path sg env
@@ -211,8 +210,7 @@ let merge_constraint initial_env loc sg constr =
make_next_first rs rem
| (Sig_module(id, md, rs) :: rem, [s], Pwith_module (_, lid))
when Ident.name id = s ->
- let path = Typetexp.find_module initial_env loc lid.txt in
- let md' = Env.find_module path env in
+ let path, md' = Typetexp.find_module initial_env loc lid.txt in
let md'' = {md' with md_type = Mtype.remove_aliases env md'.md_type} in
let newmd = Mtype.strengthen_decl env md'' path in
ignore(Includemod.modtypes env newmd.md_type md.md_type);
@@ -220,8 +218,7 @@ let merge_constraint initial_env loc sg constr =
Sig_module(id, newmd, rs) :: rem
| (Sig_module(id, md, rs) :: rem, [s], Pwith_modsubst (_, lid))
when Ident.name id = s ->
- let path = Typetexp.find_module initial_env loc lid.txt in
- let md' = Env.find_module path env in
+ let path, md' = Typetexp.find_module initial_env loc lid.txt in
let newmd = Mtype.strengthen_decl env md' path in
ignore(Includemod.modtypes env newmd.md_type md.md_type);
real_id := Some id;
@@ -250,15 +247,12 @@ let merge_constraint initial_env loc sg constr =
try match sdecl.ptype_manifest with
| Some {ptyp_desc = Ptyp_constr (lid, stl)}
when List.length stl = List.length sdecl.ptype_params ->
- let params =
- List.map
- (function {ptyp_desc=Ptyp_var s} -> s | _ -> raise Exit)
- stl in
- List.iter2 (fun x (ox, _) ->
- match ox with
- Some y when x = y.txt -> ()
- | _ -> raise Exit
- ) params sdecl.ptype_params;
+ List.iter2 (fun x (y, _) ->
+ match x, y with
+ {ptyp_desc=Ptyp_var sx}, {ptyp_desc=Ptyp_var sy}
+ when sx = sy -> ()
+ | _, _ -> raise Exit)
+ stl sdecl.ptype_params;
lid
| _ -> raise Exit
with Exit ->
@@ -272,7 +266,7 @@ let merge_constraint initial_env loc sg constr =
| [s], Pwith_modsubst (_, lid) ->
let id =
match !real_id with None -> assert false | Some id -> id in
- let path = Typetexp.find_module initial_env loc lid.txt in
+ let path = Typetexp.lookup_module initial_env loc lid.txt in
let sub = Subst.add_module id path Subst.identity in
Subst.signature sub sg
| _ ->
@@ -305,6 +299,12 @@ let rec map_rec'' fn decls rem =
fn Trec_not d1 :: map_rec'' fn dl rem
| _ -> map_rec fn decls rem
+(* Add type extension flags to extension contructors *)
+let map_ext fn exts rem =
+ match exts with
+ | [] -> rem
+ | d1 :: dl -> fn Text_first d1 :: map_end (fn Text_next) dl rem
+
(* Auxiliary for translating recursively-defined module types.
Return a module type that approximates the shape of the given module
type AST. Retain only module, type, and module type
@@ -317,7 +317,7 @@ let rec approx_modtype env smty =
let (path, info) = Typetexp.find_modtype env smty.pmty_loc lid.txt in
Mty_ident path
| Pmty_alias lid ->
- let path = Typetexp.find_module env smty.pmty_loc lid.txt in
+ let path = Typetexp.lookup_module env smty.pmty_loc lid.txt in
Mty_alias path
| Pmty_signature ssg ->
Mty_signature(approx_sig env ssg)
@@ -332,8 +332,8 @@ let rec approx_modtype env smty =
| Pmty_typeof smod ->
let (_, mty) = !type_module_type_of_fwd env smod in
mty
- | Pmty_extension (s, _arg) ->
- raise (Error (s.loc, env, Extension s.txt))
+ | Pmty_extension ext ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
and approx_module_declaration env pmd =
{
@@ -434,10 +434,10 @@ let check cl loc set_ref name =
let check_name cl set_ref name =
check cl name.loc set_ref name.txt
-let check_exn_decl loc type_names decl =
+let check_ext_decl loc type_names decl =
List.iter
(fun id -> check "type" loc type_names (Ident.name id))
- (Subst.sub_ids_exn decl)
+ (Subst.sub_ids_ext decl)
let check_sig_item type_names module_names modtype_names loc = function
Sig_type(id, _, _) ->
@@ -446,30 +446,29 @@ let check_sig_item type_names module_names modtype_names loc = function
check "module" loc module_names (Ident.name id)
| Sig_modtype(id, _) ->
check "module type" loc modtype_names (Ident.name id)
- | Sig_exception(_, decl) ->
- check_exn_decl loc type_names decl
+ | Sig_typext(_, ext, _) ->
+ check_ext_decl loc type_names ext
| _ -> ()
-let rec remove_duplicates val_ids exn_ids = function
+let rec remove_duplicates val_ids ext_ids = function
[] -> []
| Sig_value (id, _) :: rem
when List.exists (Ident.equal id) val_ids ->
- remove_duplicates val_ids exn_ids rem
- | Sig_exception(id, decl) :: rem
- when List.exists (Ident.equal id) exn_ids && Subst.sub_ids_exn decl = [] ->
- remove_duplicates val_ids exn_ids rem
- | f :: rem -> f :: remove_duplicates val_ids exn_ids rem
+ remove_duplicates val_ids ext_ids rem
+ | Sig_typext (id, decl, _) :: rem
+ when List.exists (Ident.equal id) ext_ids && Subst.sub_ids_ext decl = [] ->
+ remove_duplicates val_ids ext_ids rem
+ | f :: rem -> f :: remove_duplicates val_ids ext_ids rem
let rec get_values = function
[] -> []
| Sig_value (id, _) :: rem -> id :: get_values rem
| f :: rem -> get_values rem
-let rec get_exceptions = function
+let rec get_extension_constructors = function
[] -> []
- | Sig_exception (id, decl) :: rem -> id :: get_exceptions rem
- | f :: rem -> get_exceptions rem
-
+ | Sig_typext (id, _, _) :: rem -> id :: get_extension_constructors rem
+ | f :: rem -> get_extension_constructors rem
(* Check and translate a module type expression *)
@@ -478,7 +477,7 @@ let transl_modtype_longident loc env lid =
path
let transl_module_alias loc env lid =
- Typetexp.find_module env loc lid
+ Typetexp.lookup_module env loc lid
let mkmty desc typ env loc attrs =
let mty = {
@@ -546,8 +545,8 @@ let rec transl_modtype env smty =
| Pmty_typeof smod ->
let tmty, mty = !type_module_type_of_fwd env smod in
mkmty (Tmty_typeof tmty) mty env loc smty.pmty_attributes
- | Pmty_extension (s, _arg) ->
- raise (Error (s.loc, env, Extension s.txt))
+ | Pmty_extension ext ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
and transl_signature env sg =
let type_names = ref StringSet.empty
@@ -578,16 +577,42 @@ and transl_signature env sg =
mksig (Tsig_type decls) env loc :: trem,
prepend_sig_types decls rem,
final_env
- | Psig_exception sarg ->
- let (arg, decl, newenv) = Typedecl.transl_exception env sarg in
- check_exn_decl sarg.pcd_name.loc type_names decl;
+ | Psig_typext styext ->
+ let (tyext, newenv) =
+ Typedecl.transl_type_extension false env item.psig_loc styext
+ in
+ List.iter
+ (fun ext ->
+ check_ext_decl ext.ext_loc type_names ext.ext_type
+ )
+ tyext.tyext_constructors;
+ let (trem, rem, final_env) = transl_sig newenv srem in
+ let constructors =
+ List.filter
+ (fun ext -> not
+ (List.exists (Ident.equal ext.ext_id)
+ (get_extension_constructors rem))
+ && Subst.sub_ids_ext ext.ext_type = []
+ )
+ tyext.tyext_constructors
+ in
+ mksig (Tsig_typext tyext) env loc :: trem,
+ map_ext (fun es ext ->
+ Sig_typext(ext.ext_id, ext.ext_type, es)) constructors rem,
+ final_env
+ | Psig_exception sext ->
+ let (ext, newenv) = Typedecl.transl_exception env sext in
+ check_ext_decl ext.ext_loc type_names ext.ext_type;
let (trem, rem, final_env) = transl_sig newenv srem in
- let id = arg.cd_id in
- let trem = mksig (Tsig_exception arg) env loc :: trem in
- trem,
- (if List.exists (Ident.equal id) (get_exceptions rem)
- && Subst.sub_ids_exn decl = [] then rem
- else Sig_exception(id, decl) :: rem),
+ let shadowed =
+ List.exists
+ (Ident.equal ext.ext_id)
+ (get_extension_constructors rem)
+ && Subst.sub_ids_ext ext.ext_type = []
+ in
+ mksig (Tsig_exception ext) env loc :: trem,
+ (if shadowed then rem else
+ Sig_typext(ext.ext_id, ext.ext_type, Text_exception) :: rem),
final_env
| Psig_module pmd ->
check_name "module" module_names pmd.pmd_name;
@@ -656,7 +681,8 @@ and transl_signature env sg =
in
let (trem, rem, final_env) = transl_sig newenv srem in
mksig (Tsig_include incl) env loc :: trem,
- remove_duplicates (get_values rem) (get_exceptions rem) sg @ rem,
+ remove_duplicates (get_values rem)
+ (get_extension_constructors rem) sg @ rem,
final_env
| Psig_class cl ->
List.iter
@@ -699,15 +725,17 @@ and transl_signature env sg =
classes [rem]),
final_env
| Psig_attribute x ->
- let _back = Typetexp.warning_attribute [x] in
+ Typetexp.warning_attribute [x];
let (trem,rem, final_env) = transl_sig env srem in
mksig (Tsig_attribute x) env loc :: trem, rem, final_env
- | Psig_extension ((s, _), _) ->
- raise (Error (s.loc, env, Extension s.txt))
+ | Psig_extension (ext, _attrs) ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
in
let previous_saved_types = Cmt_format.get_saved_types () in
+ Typetexp.warning_enter_scope ();
let (trem, rem, final_env) = transl_sig (Env.in_signature env) sg in
let sg = { sig_items = trem; sig_type = rem; sig_final_env = final_env } in
+ Typetexp.warning_leave_scope ();
Cmt_format.set_saved_types
((Cmt_format.Partial_signature sg) :: previous_saved_types);
sg
@@ -1019,7 +1047,8 @@ let wrap_constraint env arg mty explicit =
let rec type_module ?(alias=false) sttn funct_body anchor env smod =
match smod.pmod_desc with
Pmod_ident lid ->
- let path = Typetexp.find_module env smod.pmod_loc lid.txt in
+ 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 path;
mod_env = env;
@@ -1144,8 +1173,8 @@ let rec type_module ?(alias=false) sttn funct_body anchor env smod =
mod_env = env;
mod_attributes = smod.pmod_attributes;
mod_loc = smod.pmod_loc }
- | Pmod_extension (s, _arg) ->
- raise (Error (s.loc, env, Extension s.txt))
+ | Pmod_extension ext ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
let type_names = ref StringSet.empty
@@ -1190,17 +1219,25 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
Tstr_type decls,
prepend_sig_types decls [],
enrich_type_decls anchor decls env newenv
- | Pstr_exception sarg ->
- let (arg, decl, newenv) = Typedecl.transl_exception env sarg in
- check_exn_decl sarg.pcd_name.loc type_names decl;
- Tstr_exception arg,
- [Sig_exception(arg.cd_id, decl)],
- newenv
- | Pstr_exn_rebind ser ->
- let (er, newenv) = Typedecl.transl_exn_rebind env ser in
- check_exn_decl ser.pexrb_name.loc type_names er.exrb_type;
- Tstr_exn_rebind er,
- [Sig_exception(er.exrb_id, er.exrb_type)],
+ | Pstr_typext styext ->
+ let (tyext, newenv) =
+ Typedecl.transl_type_extension true env loc styext
+ in
+ List.iter
+ (fun ext ->
+ check_ext_decl ext.ext_loc type_names ext.ext_type
+ )
+ tyext.tyext_constructors;
+ (Tstr_typext tyext,
+ map_ext
+ (fun es ext -> Sig_typext(ext.ext_id, ext.ext_type, es))
+ tyext.tyext_constructors [],
+ newenv)
+ | Pstr_exception sext ->
+ let (ext, newenv) = Typedecl.transl_exception env sext in
+ check_ext_decl ext.ext_loc type_names ext.ext_type;
+ Tstr_exception ext,
+ [Sig_typext(ext.ext_id, ext.ext_type, Text_exception)],
newenv
| Pstr_module {pmb_name = name; pmb_expr = smodl; pmb_attributes = attrs;
pmb_loc;
@@ -1352,8 +1389,8 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
Sig_module (id, {md with md_type =
Mty_alias (Pdot(p,Ident.name id,n))},
rs)
- | Sig_value (_, {val_kind=Val_reg}) | Sig_exception _
- | Sig_class _ as it ->
+ | Sig_value (_, {val_kind=Val_reg})
+ | Sig_typext _ | Sig_class _ as it ->
incr pos; it
| Sig_value _ | Sig_type _ | Sig_modtype _
| Sig_class_type _ as it ->
@@ -1372,10 +1409,10 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
}
in
Tstr_include incl, sg, new_env
- | Pstr_extension ((s, _), _) ->
- raise (Error (s.loc, env, Extension s.txt))
+ | Pstr_extension (ext, _attrs) ->
+ raise (Error_forward (Typetexp.error_of_extension ext))
| Pstr_attribute x ->
- let _back = Typetexp.warning_attribute [x] in
+ Typetexp.warning_attribute [x];
Tstr_attribute x, [], env
in
let rec type_struct env sstr =
@@ -1395,8 +1432,10 @@ and type_structure ?(toplevel = false) funct_body anchor env sstr scope =
(* moved to genannot *)
List.iter (function {pstr_loc = l} -> Stypes.record_phrase l) sstr;
let previous_saved_types = Cmt_format.get_saved_types () in
+ Typetexp.warning_enter_scope ();
let (items, sg, final_env) = type_struct env sstr in
let str = { str_items = items; str_type = sg; str_final_env = final_env } in
+ Typetexp.warning_leave_scope ();
Cmt_format.set_saved_types
(Cmt_format.Partial_structure str :: previous_saved_types);
str, sg, final_env
@@ -1423,7 +1462,7 @@ and normalize_signature_item env = function
| Sig_module(id, md, _) -> normalize_modtype env md.md_type
| _ -> ()
-(* Simplify multiple specifications of a value or an exception in a signature.
+(* 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. *)
@@ -1436,25 +1475,24 @@ let rec simplify_modtype mty =
| Mty_signature sg -> Mty_signature(simplify_signature sg)
and simplify_signature sg =
- let rec simplif val_names exn_names res = function
+ let rec simplif val_names ext_names res = function
[] -> res
| (Sig_value(id, descr) as component) :: sg ->
let name = Ident.name id in
- simplif (StringSet.add name val_names) exn_names
+ simplif (StringSet.add name val_names) ext_names
(if StringSet.mem name val_names then res else component :: res)
sg
- | (Sig_exception(id, decl) as component) :: sg ->
+ | (Sig_typext(id, ext, es) as component) :: sg ->
let name = Ident.name id in
- simplif val_names (StringSet.add name exn_names)
- (if StringSet.mem name exn_names && Subst.sub_ids_exn decl = []
+ simplif val_names (StringSet.add name ext_names)
+ (if StringSet.mem name ext_names && Subst.sub_ids_ext ext = []
then res else component :: res)
sg
| Sig_module(id, md, rs) :: sg ->
let md = {md with md_type = simplify_modtype md.md_type} in
- simplif val_names exn_names
- (Sig_module(id, md, rs) :: res) sg
+ simplif val_names ext_names (Sig_module(id, md, rs) :: res) sg
| component :: sg ->
- simplif val_names exn_names (component :: res) sg
+ simplif val_names ext_names (component :: res) sg
in
simplif StringSet.empty StringSet.empty [] (List.rev sg)
@@ -1464,8 +1502,7 @@ let type_module_type_of env smod =
let tmty =
match smod.pmod_desc with
| Pmod_ident lid -> (* turn off strengthening in this case *)
- let path = Typetexp.find_module env smod.pmod_loc lid.txt in
- let md = Env.find_module path env in
+ let path, md = Typetexp.find_module env smod.pmod_loc lid.txt in
rm { mod_desc = Tmod_ident (path, lid);
mod_type = md.md_type;
mod_env = env;
@@ -1538,6 +1575,7 @@ let () =
Typecore.type_package := type_package;
type_module_type_of_fwd := type_module_type_of
+
(* Typecheck an implementation file *)
let type_implementation sourcefile outputprefix modulename initial_env ast =
@@ -1545,6 +1583,11 @@ let type_implementation sourcefile outputprefix modulename initial_env ast =
try
Typecore.reset_delayed_checks ();
Env.reset_required_globals ();
+ begin
+ let map = Typetexp.emit_external_warnings in
+ ignore (map.Ast_mapper.structure map ast)
+ end;
+
let (str, sg, finalenv) =
type_structure initial_env ast (Location.in_file sourcefile) in
let simple_sg = simplify_signature sg in
@@ -1563,7 +1606,8 @@ let type_implementation sourcefile outputprefix modulename initial_env ast =
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 sourcefile sg intf_file dclsig in
+ let coercion =
+ Includemod.compunit initial_env 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
@@ -1575,7 +1619,7 @@ let type_implementation sourcefile outputprefix modulename initial_env ast =
check_nongen_schemes finalenv str.str_items;
normalize_signature finalenv simple_sg;
let coercion =
- Includemod.compunit sourcefile sg
+ Includemod.compunit initial_env sourcefile sg
"(inferred signature)" simple_sg in
Typecore.force_delayed_checks ();
(* See comment above. Here the target signature contains all
@@ -1604,6 +1648,13 @@ let save_signature modname tsg outputprefix source_file initial_env cmi =
Cmt_format.save_cmt (outputprefix ^ ".cmti") modname
(Cmt_format.Interface tsg) (Some source_file) initial_env (Some cmi)
+let type_interface env ast =
+ begin
+ let map = Typetexp.emit_external_warnings in
+ ignore (map.Ast_mapper.signature map ast)
+ end;
+ transl_signature env ast
+
(* "Packaging" of several compilation units into one unit
having them as sub-modules. *)
@@ -1620,7 +1671,7 @@ let rec package_signatures subst = function
Trec_not) ::
package_signatures (Subst.add_module oldid (Pident newid) subst) rem
-let package_units objfiles cmifile modulename =
+let package_units initial_env objfiles cmifile modulename =
(* Read the signatures of the units *)
let units =
List.map
@@ -1629,7 +1680,7 @@ let package_units objfiles cmifile modulename =
let modname = String.capitalize(Filename.basename pref) in
let sg = Env.read_signature modname (pref ^ ".cmi") in
if Filename.check_suffix f ".cmi" &&
- not(Mtype.no_code_needed_sig Env.initial sg)
+ not(Mtype.no_code_needed_sig Env.initial_safe_string sg)
then raise(Error(Location.none, Env.empty,
Implementation_is_required f));
(modname, Env.read_signature modname (pref ^ ".cmi")))
@@ -1647,22 +1698,22 @@ let package_units objfiles cmifile modulename =
end;
let dclsig = Env.read_signature modulename cmifile in
Cmt_format.save_cmt (prefix ^ ".cmt") modulename
- (Cmt_format.Packed (sg, objfiles)) None Env.initial None ;
- Includemod.compunit "(obtained by packing)" sg mlifile dclsig
+ (Cmt_format.Packed (sg, objfiles)) None initial_env None ;
+ Includemod.compunit initial_env "(obtained by packing)" sg mlifile dclsig
end else begin
(* Determine imports *)
let unit_names = List.map fst units in
let imports =
List.filter
(fun (name, crc) -> not (List.mem name unit_names))
- (Env.imported_units()) in
+ (Env.imports()) in
(* Write packaged signature *)
if not !Clflags.dont_write_files then begin
let sg =
Env.save_signature_with_imports sg modulename
(prefix ^ ".cmi") imports in
Cmt_format.save_cmt (prefix ^ ".cmt") modulename
- (Cmt_format.Packed (sg, objfiles)) None Env.initial (Some sg)
+ (Cmt_format.Packed (sg, objfiles)) None initial_env (Some sg)
end;
Tcoerce_none
end
@@ -1745,8 +1796,6 @@ let report_error ppf = function
"The type %a in this module cannot be exported.@ " longident lid;
fprintf ppf
"Its type contains local dependencies:@ %a" type_expr ty
- | Extension s ->
- fprintf ppf "Uninterpreted extension '%s'." s
| Recursive_module_require_explicit_type ->
fprintf ppf "Recursive modules require an explicit module type."
| Apply_generative ->
@@ -1760,6 +1809,8 @@ let () =
(function
| Error (loc, env, err) ->
Some (Location.error_of_printer loc (report_error env) err)
+ | Error_forward err ->
+ Some err
| _ ->
None
)
diff --git a/typing/typemod.mli b/typing/typemod.mli
index 051a283609..8895017885 100644
--- a/typing/typemod.mli
+++ b/typing/typemod.mli
@@ -26,18 +26,24 @@ val type_toplevel_phrase:
val type_implementation:
string -> string -> string -> Env.t -> Parsetree.structure ->
Typedtree.structure * Typedtree.module_coercion
+val type_interface:
+ Env.t -> Parsetree.signature -> Typedtree.signature
val transl_signature:
Env.t -> Parsetree.signature -> Typedtree.signature
val check_nongen_schemes:
Env.t -> Typedtree.structure_item list -> unit
+val type_open_:
+ ?toplevel:bool -> Asttypes.override_flag ->
+ Env.t -> Location.t -> Longident.t Asttypes.loc -> Path.t * Env.t
val simplify_signature: signature -> signature
-val save_signature : string -> Typedtree.signature -> string -> string ->
+val save_signature:
+ string -> Typedtree.signature -> string -> string ->
Env.t -> Types.signature_item list -> unit
val package_units:
- string list -> string -> string -> Typedtree.module_coercion
+ Env.t -> string list -> string -> string -> Typedtree.module_coercion
type error =
Cannot_apply of module_type
@@ -58,10 +64,10 @@ type error =
| Not_a_packed_module of type_expr
| Incomplete_packed_module of type_expr
| Scoping_pack of Longident.t * type_expr
- | Extension of string
| Recursive_module_require_explicit_type
| Apply_generative
exception Error of Location.t * Env.t * error
+exception Error_forward of Location.error
val report_error: Env.t -> formatter -> error -> unit
diff --git a/typing/types.ml b/typing/types.ml
index 57328026d1..2b3f26ce6f 100644
--- a/typing/types.ml
+++ b/typing/types.ml
@@ -125,7 +125,8 @@ type constructor_description =
and constructor_tag =
Cstr_constant of int (* Constant constructor (an int) *)
| Cstr_block of int (* Regular constructor (a block) *)
- | Cstr_exception of Path.t * Location.t (* Exception constructor *)
+ | Cstr_extension of Path.t * bool (* Extension constructor
+ true if a constant false if a block *)
(* Record label descriptions *)
@@ -146,7 +147,7 @@ and record_representation =
Record_regular (* All fields are boxed / tagged *)
| Record_inlined of int (* Same, for inlined records *)
| Record_float (* All fields are floats *)
- | Record_exception of Path.t (* Inlined record under exception *)
+ | Record_extension of Path.t (* Inlined record under exception *)
(* Variance *)
@@ -196,6 +197,7 @@ and type_kind =
Type_abstract
| Type_record of label_declaration list * record_representation
| Type_variant of constructor_declaration list
+ | Type_open
and label_declaration =
{
@@ -219,17 +221,20 @@ and constructor_arguments =
| Cstr_tuple of type_expr list
| Cstr_record of Ident.t * label_declaration list
+type extension_constructor =
+ { ext_type_path: Path.t;
+ ext_type_params: type_expr list;
+ ext_args: constructor_arguments;
+ ext_ret_type: type_expr option;
+ ext_private: private_flag;
+ ext_loc: Location.t;
+ ext_attributes: Parsetree.attributes; }
+
and type_transparence =
Type_public (* unrestricted expansion *)
| Type_new (* "new" type *)
| Type_private (* private type *)
-type exception_declaration =
- { exn_args: constructor_arguments;
- exn_loc: Location.t;
- exn_attributes: Parsetree.attributes;
- }
-
(* Type expressions for the class language *)
module Concr = Set.Make(OrderedString)
@@ -278,7 +283,7 @@ 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_exception of Ident.t * exception_declaration
+ | 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
@@ -302,3 +307,8 @@ and rec_status =
Trec_not (* not recursive *)
| Trec_first (* first in a recursive group *)
| Trec_next (* not first in a recursive group *)
+
+and ext_status =
+ Text_first (* first constructor of an extension *)
+ | Text_next (* not first constructor of an extension *)
+ | Text_exception (* an exception *)
diff --git a/typing/types.mli b/typing/types.mli
index d268ddafa7..9fc3d0dc14 100644
--- a/typing/types.mli
+++ b/typing/types.mli
@@ -122,7 +122,8 @@ type constructor_description =
and constructor_tag =
Cstr_constant of int (* Constant constructor (an int) *)
| Cstr_block of int (* Regular constructor (a block) *)
- | Cstr_exception of Path.t * Location.t (* Exception constructor *)
+ | Cstr_extension of Path.t * bool (* Extension constructor
+ true if a constant false if a block *)
(* Record label descriptions *)
@@ -143,7 +144,7 @@ and record_representation =
Record_regular (* All fields are boxed / tagged *)
| Record_inlined of int (* Same, for inlined records *)
| Record_float (* All fields are floats *)
- | Record_exception of Path.t (* Inlined record under exception *)
+ | Record_extension of Path.t (* Inlined record under extension *)
(* Variance *)
@@ -184,6 +185,7 @@ and type_kind =
Type_abstract
| Type_record of label_declaration list * record_representation
| Type_variant of constructor_declaration list
+ | Type_open
and label_declaration =
{
@@ -207,17 +209,22 @@ and constructor_arguments =
| Cstr_tuple of type_expr list
| Cstr_record of Ident.t * label_declaration list
+type extension_constructor =
+ {
+ ext_type_path: Path.t;
+ ext_type_params: type_expr list;
+ ext_args: constructor_arguments;
+ ext_ret_type: type_expr option;
+ ext_private: private_flag;
+ ext_loc: Location.t;
+ ext_attributes: Parsetree.attributes;
+ }
+
and type_transparence =
Type_public (* unrestricted expansion *)
| Type_new (* "new" type *)
| Type_private (* private type *)
-type exception_declaration =
- { exn_args: constructor_arguments;
- exn_loc: Location.t;
- exn_attributes: Parsetree.attributes;
- }
-
(* Type expressions for the class language *)
module Concr : Set.S with type elt = string
@@ -266,7 +273,7 @@ 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_exception of Ident.t * exception_declaration
+ | 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
@@ -290,3 +297,8 @@ and rec_status =
Trec_not (* not recursive *)
| Trec_first (* first in a recursive group *)
| Trec_next (* not first in a recursive group *)
+
+and ext_status =
+ Text_first (* first constructor in an extension *)
+ | Text_next (* not first constructor in an extension *)
+ | Text_exception
diff --git a/typing/typetexp.ml b/typing/typetexp.ml
index b219c814a8..31d4a44f1b 100644
--- a/typing/typetexp.ml
+++ b/typing/typetexp.ml
@@ -21,7 +21,7 @@ open Typedtree
open Types
open Ctype
-exception Already_bound of Location.t
+exception Already_bound
type error =
Unbound_type_variable of string
@@ -51,48 +51,118 @@ type error =
| Unbound_cltype of Longident.t
| Ill_typed_functor_application of Longident.t
| Illegal_reference_to_recursive_module
- | Extension of string
+ | Access_functor_as_structure of Longident.t
exception Error of Location.t * Env.t * error
+exception Error_forward of Location.error
+
+let string_of_cst = function
+ | Const_string(s, _) -> Some s
+ | _ -> None
+
+let string_of_payload = function
+ | PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_constant c},_)}] ->
+ string_of_cst c
+ | _ -> None
+
+let rec error_of_extension ext =
+ 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
+ | {pstr_loc} :: rest ->
+ (Location.errorf ~loc
+ "Invalid syntax for sub-error of extension '%s'." txt) ::
+ sub_from rest
+ | [] -> []
+ in
+ begin match p with
+ | PStr({pstr_desc=Pstr_eval
+ ({pexp_desc=Pexp_constant(Const_string(msg,_))}, _)}::
+ {pstr_desc=Pstr_eval
+ ({pexp_desc=Pexp_constant(Const_string(if_highlight,_))}, _)}::
+ inner) ->
+ Location.error ~loc ~if_highlight ~sub:(sub_from inner) msg
+ | PStr({pstr_desc=Pstr_eval
+ ({pexp_desc=Pexp_constant(Const_string(msg,_))}, _)}::inner) ->
+ Location.error ~loc ~sub:(sub_from inner) msg
+ | _ -> Location.errorf ~loc "Invalid syntax for extension '%s'." txt
+ end
+ | ({txt; loc}, _) ->
+ Location.errorf ~loc "Uninterpreted extension '%s'." txt
let check_deprecated loc attrs s =
- if
- List.exists
- (function ({txt = "ocaml.deprecated"; _}, _) -> true | _ -> false)
- attrs
- then
- Location.prerr_warning loc (Warnings.Deprecated s)
+ List.iter
+ (function
+ | ({txt = "ocaml.deprecated"|"deprecated"; _}, p) ->
+ begin match string_of_payload p with
+ | Some txt ->
+ Location.prerr_warning loc (Warnings.Deprecated (s ^ "\n" ^ txt))
+ | None ->
+ Location.prerr_warning loc (Warnings.Deprecated s)
+ end
+ | _ -> ())
+ attrs
+
+let emit_external_warnings =
+ let open Ast_mapper in
+ {
+ default_mapper with
+ attribute = (fun _ a ->
+ begin match a with
+ | {txt="ocaml.ppwarning"|"ppwarning"},
+ PStr[{pstr_desc=Pstr_eval({pexp_desc=Pexp_constant
+ (Const_string (s, _))},_);
+ pstr_loc}] ->
+ Location.prerr_warning pstr_loc (Warnings.Preprocessor s)
+ | _ -> ()
+ end;
+ a
+ )
+ }
+
+
+let warning_scope = ref []
+
+let warning_enter_scope () =
+ warning_scope := ref None :: !warning_scope
+let warning_leave_scope () =
+ match !warning_scope with
+ | [] -> assert false
+ | hd :: tl ->
+ may Warnings.restore !hd;
+ warning_scope := tl
let warning_attribute attrs =
- let prev_warnings = ref None in
+ let prev_warnings = List.hd !warning_scope in
+ let process loc txt errflag payload =
+ match string_of_payload payload with
+ | Some s ->
+ if !prev_warnings = None then
+ prev_warnings := Some (Warnings.backup ());
+ begin try Warnings.parse_options errflag s
+ with Arg.Bad _ ->
+ Location.prerr_warning loc
+ (Warnings.Attribute_payload
+ (txt, "Ill-formed list of warnings"))
+ end
+ | None ->
+ Location.prerr_warning loc
+ (Warnings.Attribute_payload
+ (txt, "A single string literal is expected"))
+ in
List.iter
(function
- | ({txt = "ocaml.warning"; loc}, payload) ->
- begin match payload with
- | PStr [{pstr_desc=Pstr_eval
- ({pexp_desc=Pexp_constant(Const_string(s, _))}, _)}] ->
- if !prev_warnings = None then
- prev_warnings := Some (Warnings.backup ());
- begin try Warnings.parse_options false s
- with Arg.Bad _ ->
- Location.prerr_warning loc
- (Warnings.Attribute_payload
- ("ocaml.warning",
- "Ill-formed list of warnings"))
- end
- | _ ->
- Location.prerr_warning loc
- (Warnings.Attribute_payload
- ("ocaml.warning",
- "A single string literal is expected"))
- end
+ | ({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
| _ ->
()
)
- attrs;
- !prev_warnings
-
-
+ attrs
type variable_context = int * (string, type_expr) Tbl.t
@@ -105,16 +175,22 @@ let instance_list = Ctype.instance_list Env.empty
let rec narrow_unbound_lid_error : 'a. _ -> _ -> _ -> _ -> 'a =
fun env loc lid make_error ->
let check_module mlid =
- try ignore (Env.lookup_module mlid env)
- with Not_found ->
- narrow_unbound_lid_error env loc mlid
- (fun lid -> Unbound_module lid)
- | Env.Recmodule ->
- raise (Error (loc, env, Illegal_reference_to_recursive_module))
+ try ignore (Env.lookup_module true mlid env) with
+ | Not_found ->
+ narrow_unbound_lid_error env loc mlid (fun lid -> Unbound_module lid)
+ | Env.Recmodule ->
+ raise (Error (loc, env, Illegal_reference_to_recursive_module))
in
begin match lid with
| Longident.Lident _ -> ()
- | Longident.Ldot (mlid, _) -> check_module mlid
+ | Longident.Ldot (mlid, _) ->
+ check_module mlid;
+ let md = Env.find_module (Env.lookup_module true mlid env) env in
+ begin match Env.scrape_alias env md.md_type with
+ Mty_functor _ ->
+ raise (Error (loc, env, Access_functor_as_structure mlid))
+ | _ -> ()
+ end
| Longident.Lapply (flid, mlid) ->
check_module flid;
check_module mlid;
@@ -126,7 +202,7 @@ let find_component lookup make_error env loc lid =
try
match lid with
| Longident.Ldot (Longident.Lident "*predef*", s) ->
- lookup (Longident.Lident s) Env.initial
+ lookup (Longident.Lident s) Env.initial_safe_string
| _ -> lookup lid env
with Not_found ->
narrow_unbound_lid_error env loc lid make_error
@@ -165,13 +241,17 @@ let find_value env loc lid =
check_deprecated loc decl.val_attributes (Path.name path);
r
-let find_module env loc lid =
+let lookup_module ?(load=false) env loc lid =
let (path, decl) as r =
- find_component (fun lid env -> (Env.lookup_module lid env, ()))
+ find_component (fun lid env -> (Env.lookup_module ~load lid env, ()))
(fun lid -> Unbound_module lid) env loc lid
- in
- (* check_deprecated loc decl.md_attributes (Path.name path); *)
- path
+ in path
+
+let find_module env loc lid =
+ let path = lookup_module ~load:true env loc lid in
+ let decl = Env.find_module path env in
+ check_deprecated loc decl.md_attributes (Path.name path);
+ (path, decl)
let find_modtype env loc lid =
let (path, decl) as r =
@@ -258,24 +338,35 @@ let new_global_var ?name () =
let newvar ?name () =
newvar ?name:(validate_name name) ()
-let enter_type_variable {Location.txt=name; loc} =
- try
- if name <> "" && name.[0] = '_' then
- raise (Error (loc, Env.empty, Invalid_variable_name ("'" ^ name)));
- let v = Tbl.find name !type_variables in
- raise (Already_bound loc);
- v
- with Not_found ->
- let v = new_global_var ~name () in
- type_variables := Tbl.add name v !type_variables;
- v
-
let type_variable loc name =
try
Tbl.find name !type_variables
with Not_found ->
raise(Error(loc, Env.empty, Unbound_type_variable ("'" ^ name)))
+let transl_type_param env styp =
+ let loc = styp.ptyp_loc in
+ match styp.ptyp_desc with
+ Ptyp_any ->
+ let ty = new_global_var ~name:"_" () in
+ { ctyp_desc = Ttyp_any; ctyp_type = ty; ctyp_env = env;
+ ctyp_loc = loc; ctyp_attributes = styp.ptyp_attributes; }
+ | Ptyp_var name ->
+ let ty =
+ try
+ if name <> "" && name.[0] = '_' then
+ raise (Error (loc, Env.empty, Invalid_variable_name ("'" ^ name)));
+ ignore (Tbl.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;
+ v
+ in
+ { ctyp_desc = Ttyp_var name; ctyp_type = ty; ctyp_env = env;
+ ctyp_loc = loc; ctyp_attributes = styp.ptyp_attributes; }
+ | _ -> assert false
+
let wrap_method ty =
match (Ctype.repr ty).desc with
Tpoly _ -> ty
@@ -366,7 +457,7 @@ let rec transl_type env policy styp =
ctyp (Ttyp_constr (path, lid, args)) constr
| Ptyp_object (fields, o) ->
let fields =
- List.map (fun (s, t) -> (s, transl_poly_type env policy t))
+ List.map (fun (s, a, t) -> (s, a, transl_poly_type env policy t))
fields
in
let ty = newobj (transl_fields loc env policy [] o fields) in
@@ -398,7 +489,7 @@ let rec transl_type env policy styp =
let (path, decl) = Env.lookup_type lid2 env in
(path, decl, false)
with Not_found ->
- raise(Error(styp.ptyp_loc, env, Unbound_class lid.txt))
+ ignore (find_class env styp.ptyp_loc lid.txt); assert false
in
if List.length stl <> decl.type_arity then
raise(Error(styp.ptyp_loc, env,
@@ -508,7 +599,7 @@ let rec transl_type env policy styp =
Hashtbl.add hfields h (l,f)
in
let add_field = function
- Rtag (l, c, stl) ->
+ Rtag (l, attrs, c, stl) ->
name := None;
let tl = List.map (transl_type env policy) stl in
let f = match present with
@@ -523,7 +614,7 @@ let rec transl_type env policy styp =
Rpresent (Some st.ctyp_type)
in
add_typed_field styp.ptyp_loc l f;
- Ttag (l,c,tl)
+ Ttag (l,attrs,c,tl)
| Rinherit sty ->
let cty = transl_type env policy sty in
let ty = cty.ctyp_type in
@@ -629,13 +720,13 @@ let rec transl_type env policy styp =
List.map (fun (_,cty) -> cty.ctyp_type) ptys))
in
ctyp (Ttyp_package {
- pack_name = path;
+ pack_path = path;
pack_type = mty.mty_type;
pack_fields = ptys;
pack_txt = p;
}) ty
- | Ptyp_extension (s, _arg) ->
- raise (Error (s.loc, env, Extension s.txt))
+ | Ptyp_extension ext ->
+ raise (Error_forward (error_of_extension ext))
and transl_poly_type env policy t =
transl_type env policy (Ast_helper.Typ.force_poly t)
@@ -648,7 +739,7 @@ and transl_fields loc env policy seen o =
| Open, Univars -> new_pre_univar ()
| Open, _ -> newvar ()
end
- | (s, ty1) :: l ->
+ | (s, _attrs, ty1) :: l ->
if List.mem s seen then raise (Error (loc, env, Repeated_method_label s));
let ty2 = transl_fields loc env policy (s :: seen) o l in
newty (Tfield (s, Fpresent, ty1.ctyp_type, ty2))
@@ -903,14 +994,16 @@ let report_error env ppf = function
fprintf ppf "Ill-typed functor application %a" longident lid
| Illegal_reference_to_recursive_module ->
fprintf ppf "Illegal recursive module reference"
- | Extension s ->
- fprintf ppf "Uninterpreted extension '%s'." s
+ | Access_functor_as_structure lid ->
+ fprintf ppf "The module %a is a functor, not a structure" longident lid
let () =
Location.register_error_of_exn
(function
| Error (loc, env, err) ->
Some (Location.error_of_printer loc (report_error env) err)
+ | Error_forward err ->
+ Some err
| _ ->
None
)
diff --git a/typing/typetexp.mli b/typing/typetexp.mli
index 1d90eb7591..7bff403f0f 100644
--- a/typing/typetexp.mli
+++ b/typing/typetexp.mli
@@ -25,14 +25,15 @@ val transl_simple_type_delayed:
val transl_type_scheme:
Env.t -> Parsetree.core_type -> Typedtree.core_type
val reset_type_variables: unit -> unit
-val enter_type_variable: string Location.loc -> type_expr
val type_variable: Location.t -> string -> type_expr
+val transl_type_param:
+ Env.t -> Parsetree.core_type -> Typedtree.core_type
type variable_context
val narrow: unit -> variable_context
val widen: variable_context -> unit
-exception Already_bound of Location.t
+exception Already_bound
type error =
Unbound_type_variable of string
@@ -62,7 +63,7 @@ type error =
| Unbound_cltype of Longident.t
| Ill_typed_functor_application of Longident.t
| Illegal_reference_to_recursive_module
- | Extension of string
+ | Access_functor_as_structure of Longident.t
exception Error of Location.t * Env.t * error
@@ -95,7 +96,9 @@ val find_value:
val find_class:
Env.t -> Location.t -> Longident.t -> Path.t * class_declaration
val find_module:
- Env.t -> Location.t -> Longident.t -> Path.t
+ Env.t -> Location.t -> Longident.t -> Path.t * module_declaration
+val lookup_module:
+ ?load:bool -> Env.t -> Location.t -> Longident.t -> Path.t
val find_modtype:
Env.t -> Location.t -> Longident.t -> Path.t * modtype_declaration
val find_class_type:
@@ -112,4 +115,10 @@ val spellcheck_simple:
val check_deprecated: Location.t -> Parsetree.attributes -> string -> unit
-val warning_attribute: Parsetree.attributes -> Warnings.state option
+val warning_enter_scope: unit -> unit
+val warning_leave_scope: unit -> unit
+val warning_attribute: Parsetree.attributes -> unit
+
+val error_of_extension: Parsetree.extension -> Location.error
+
+val emit_external_warnings: Ast_mapper.mapper
diff --git a/utils/clflags.ml b/utils/clflags.ml
index 829393a00d..f582a46559 100644
--- a/utils/clflags.ml
+++ b/utils/clflags.ml
@@ -43,6 +43,7 @@ and noprompt = ref false (* -noprompt *)
and nopromptcont = ref false (* -nopromptcont *)
and init_file = ref (None : string option) (* -init *)
and noinit = ref false (* -noinit *)
+and open_modules = ref [] (* -open *)
and use_prims = ref "" (* -use-prims ... *)
and use_runtime = ref "" (* -use-runtime ... *)
and principal = ref false (* -principal *)
@@ -58,6 +59,7 @@ and dllpaths = ref ([] : string list) (* -dllpath *)
and make_package = ref false (* -pack *)
and for_package = ref (None: string option) (* -for-pack *)
and error_size = ref 500 (* -error-size *)
+and float_const_prop = ref true (* -no-float-const-prop *)
and transparent_modules = ref false (* -trans-mod *)
let dump_source = ref false (* -dsource *)
let dump_parsetree = ref false (* -dparsetree *)
@@ -72,6 +74,7 @@ let optimize_for_speed = ref true (* -compact *)
and dump_cmm = ref false (* -dcmm *)
let dump_selection = ref false (* -dsel *)
+let dump_cse = ref false (* -dcse *)
let dump_live = ref false (* -dlive *)
let dump_spill = ref false (* -dspill *)
let dump_split = ref false (* -dsplit *)
@@ -105,3 +108,4 @@ let dlcode = ref true (* not -nodynlink *)
let runtime_variant = ref "";; (* -runtime-variant *)
let keep_locs = ref false (* -keep-locs *)
+let unsafe_string = ref true;; (* -safe-string / -unsafe-string *)
diff --git a/utils/clflags.mli b/utils/clflags.mli
index 876776acdb..5474157c37 100644
--- a/utils/clflags.mli
+++ b/utils/clflags.mli
@@ -23,11 +23,12 @@ val debug : bool ref
val fast : bool ref
val link_everything : bool ref
val custom_runtime : bool ref
-val bytecode_compatible_32: bool ref
+val bytecode_compatible_32 : bool ref
val output_c_object : bool ref
val all_ccopts : string list ref
val classic : bool ref
val nopervasives : bool ref
+val open_modules : string list ref
val preprocessor : string option ref
val all_ppx : string list ref
val annotations : bool ref
@@ -55,6 +56,7 @@ val dllpaths : string list ref
val make_package : bool ref
val for_package : string option ref
val error_size : int ref
+val float_const_prop : bool ref
val transparent_modules : bool ref
val dump_source : bool ref
val dump_parsetree : bool ref
@@ -67,6 +69,7 @@ val keep_asm_file : bool ref
val optimize_for_speed : bool ref
val dump_cmm : bool ref
val dump_selection : bool ref
+val dump_cse : bool ref
val dump_live : bool ref
val dump_spill : bool ref
val dump_split : bool ref
@@ -88,3 +91,4 @@ val dlcode : bool ref
val runtime_variant : string ref
val force_slash : bool ref
val keep_locs : bool ref
+val unsafe_string : bool ref
diff --git a/utils/config.mlp b/utils/config.mlp
index 209f90ce15..db6fd20ed0 100644
--- a/utils/config.mlp
+++ b/utils/config.mlp
@@ -50,14 +50,14 @@ let mkmaindll = "%%MKMAINDLL%%"
let exec_magic_number = "Caml1999X011"
and cmi_magic_number = "Caml1999I017"
-and cmo_magic_number = "Caml1999O009"
-and cma_magic_number = "Caml1999A010"
-and cmx_magic_number = "Caml1999Y012"
-and cmxa_magic_number = "Caml1999Z011"
+and cmo_magic_number = "Caml1999O010"
+and cma_magic_number = "Caml1999A011"
+and cmx_magic_number = "Caml1999Y014"
+and cmxa_magic_number = "Caml1999Z013"
and ast_impl_magic_number = "Caml1999M016"
and ast_intf_magic_number = "Caml1999N015"
-and cmxs_magic_number = "Caml2007D001"
-and cmt_magic_number = "Caml2012T003"
+and cmxs_magic_number = "Caml2007D002"
+and cmt_magic_number = "Caml2012T004"
let load_path = ref ([] : string list)
diff --git a/utils/consistbl.ml b/utils/consistbl.ml
index 4bc42dc5b0..6adaf41122 100644
--- a/utils/consistbl.ml
+++ b/utils/consistbl.ml
@@ -40,8 +40,19 @@ let set tbl name crc source = Hashtbl.add tbl name (crc, source)
let source tbl name = snd (Hashtbl.find tbl name)
-let extract tbl =
- Hashtbl.fold (fun name (crc, auth) accu -> (name, crc) :: accu) tbl []
+let extract l tbl =
+ List.fold_left
+ (fun assc name ->
+ try
+ ignore (List.assoc name assc);
+ assc
+ with Not_found ->
+ try
+ let (crc, _) = Hashtbl.find tbl name in
+ (name, Some crc) :: assc
+ with Not_found ->
+ (name, None) :: assc)
+ [] l
let filter p tbl =
let to_remove = ref [] in
diff --git a/utils/consistbl.mli b/utils/consistbl.mli
index d3f2afcec9..012bd734fa 100644
--- a/utils/consistbl.mli
+++ b/utils/consistbl.mli
@@ -40,9 +40,10 @@ val source: t -> string -> string
if the latter has an associated CRC in [tbl].
Raise [Not_found] otherwise. *)
-val extract: t -> (string * Digest.t) list
- (* Return all bindings ([name], [crc]) contained in the given
- table. *)
+val extract: string list -> t -> (string * Digest.t option) list
+ (* [extract tbl names] returns an associative list mapping each string
+ in [names] to the CRC associated with it in [tbl]. If no CRC is
+ associated with a name then it is mapped to [None]. *)
val filter: (string -> bool) -> t -> unit
(* [filter pred tbl] removes from [tbl] table all (name, CRC) pairs
diff --git a/utils/misc.ml b/utils/misc.ml
index 1a2a871394..898880cb07 100644
--- a/utils/misc.ml
+++ b/utils/misc.ml
@@ -124,14 +124,14 @@ let create_hashtable size init =
(* File copy *)
let copy_file ic oc =
- let buff = String.create 0x1000 in
+ let buff = Bytes.create 0x1000 in
let rec copy () =
let n = input ic buff 0 0x1000 in
if n = 0 then () else (output oc buff 0 n; copy())
in copy()
let copy_file_chunk ic oc len =
- let buff = String.create 0x1000 in
+ let buff = Bytes.create 0x1000 in
let rec copy n =
if n <= 0 then () else begin
let r = input ic buff 0 (min n 0x1000) in
@@ -141,23 +141,13 @@ let copy_file_chunk ic oc len =
let string_of_file ic =
let b = Buffer.create 0x10000 in
- let buff = String.create 0x1000 in
+ let buff = Bytes.create 0x1000 in
let rec copy () =
let n = input ic buff 0 0x1000 in
if n = 0 then Buffer.contents b else
- (Buffer.add_substring b buff 0 n; copy())
+ (Buffer.add_subbytes b buff 0 n; copy())
in copy()
-
-
-(* Reading from a channel *)
-
-let input_bytes ic n =
- let result = String.create n in
- really_input ic result 0 n;
- result
-;;
-
(* Integer operations *)
let rec log2 n =
@@ -226,26 +216,27 @@ let for4 (_,_,_,x) = x
module LongString = struct
- type t = string array
+ type t = bytes array
let create str_size =
let tbl_size = str_size / Sys.max_string_length + 1 in
- let tbl = Array.make tbl_size "" in
+ let tbl = Array.make tbl_size Bytes.empty in
for i = 0 to tbl_size - 2 do
- tbl.(i) <- String.create Sys.max_string_length;
+ tbl.(i) <- Bytes.create Sys.max_string_length;
done;
- tbl.(tbl_size - 1) <- String.create (str_size mod Sys.max_string_length);
+ tbl.(tbl_size - 1) <- Bytes.create (str_size mod Sys.max_string_length);
tbl
let length tbl =
let tbl_size = Array.length tbl in
- Sys.max_string_length * (tbl_size - 1) + String.length tbl.(tbl_size - 1)
+ Sys.max_string_length * (tbl_size - 1) + Bytes.length tbl.(tbl_size - 1)
let get tbl ind =
- tbl.(ind / Sys.max_string_length).[ind mod Sys.max_string_length]
+ Bytes.get tbl.(ind / Sys.max_string_length) (ind mod Sys.max_string_length)
let set tbl ind c =
- tbl.(ind / Sys.max_string_length).[ind mod Sys.max_string_length] <- c
+ Bytes.set tbl.(ind / Sys.max_string_length) (ind mod Sys.max_string_length)
+ c
let blit src srcoff dst dstoff len =
for i = 0 to len - 1 do
@@ -257,14 +248,14 @@ module LongString = struct
output_char oc (get tbl i)
done
- let unsafe_blit_to_string src srcoff dst dstoff len =
+ let unsafe_blit_to_bytes src srcoff dst dstoff len =
for i = 0 to len - 1 do
- String.unsafe_set dst (dstoff + i) (get src (srcoff + i))
+ Bytes.unsafe_set dst (dstoff + i) (get src (srcoff + i))
done
let input_bytes ic len =
let tbl = create len in
- Array.iter (fun str -> really_input ic str 0 (String.length str)) tbl;
+ Array.iter (fun str -> really_input ic str 0 (Bytes.length str)) tbl;
tbl
end
diff --git a/utils/misc.mli b/utils/misc.mli
index 67316365e1..4a3c84b2d9 100644
--- a/utils/misc.mli
+++ b/utils/misc.mli
@@ -66,11 +66,6 @@ val copy_file_chunk: in_channel -> out_channel -> int -> unit
val string_of_file: in_channel -> string
(* [string_of_file ic] reads the contents of file [ic] and copies
them to a string. It stops when encountering EOF on [ic]. *)
-val input_bytes : in_channel -> int -> string;;
- (* [input_bytes ic n] reads [n] bytes from [ic] and returns them
- in a new string. It raises [End_of_file] if EOF is encountered
- before all the bytes are read. *)
-
val log2: int -> int
(* [log2 n] returns [s] such that [n = 1 lsl s]
if [n] is a power of 2*)
@@ -124,14 +119,14 @@ val for4: 'a * 'b * 'c * 'd -> 'd
module LongString :
sig
- type t = string array
+ type t = bytes array
val create : int -> t
val length : t -> int
val get : t -> int -> char
val set : t -> int -> char -> unit
val blit : t -> int -> t -> int -> int -> unit
val output : out_channel -> t -> int -> int -> unit
- val unsafe_blit_to_string : t -> int -> string -> int -> int -> unit
+ val unsafe_blit_to_bytes : t -> int -> bytes -> int -> int -> unit
val input_bytes : in_channel -> int -> t
end
diff --git a/utils/warnings.ml b/utils/warnings.ml
index 58d2753962..2dc26a3504 100644
--- a/utils/warnings.ml
+++ b/utils/warnings.ml
@@ -39,7 +39,7 @@ type t =
| Without_principality of string (* 19 *)
| Unused_argument (* 20 *)
| Nonreturning_statement (* 21 *)
- | Camlp4 of string (* 22 *)
+ | Preprocessor of string (* 22 *)
| Useless_record_with (* 23 *)
| Bad_module_name of string (* 24 *)
| All_clauses_guarded (* 25 *)
@@ -55,7 +55,7 @@ type t =
| Unused_for_index of string (* 35 *)
| Unused_ancestor of string (* 36 *)
| Unused_constructor of string * bool * bool (* 37 *)
- | Unused_exception of string * bool (* 38 *)
+ | Unused_extension of string * 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 *)
@@ -66,6 +66,7 @@ type t =
| Bad_env_variable of string * string (* 46 *)
| Attribute_payload of string * string (* 47 *)
| Eliminated_optional_arguments of string list (* 48 *)
+ | No_cmi_file of string (* 49 *)
;;
(* If you remove a warning, leave a hole in the numbering. NEVER change
@@ -96,7 +97,7 @@ let number = function
| Without_principality _ -> 19
| Unused_argument -> 20
| Nonreturning_statement -> 21
- | Camlp4 _ -> 22
+ | Preprocessor _ -> 22
| Useless_record_with -> 23
| Bad_module_name _ -> 24
| All_clauses_guarded -> 25
@@ -112,7 +113,7 @@ let number = function
| Unused_for_index _ -> 35
| Unused_ancestor _ -> 36
| Unused_constructor _ -> 37
- | Unused_exception _ -> 38
+ | Unused_extension _ -> 38
| Unused_rec_flag -> 39
| Name_out_of_scope _ -> 40
| Ambiguous_name _ -> 41
@@ -123,9 +124,10 @@ let number = function
| Bad_env_variable _ -> 46
| Attribute_payload _ -> 47
| Eliminated_optional_arguments _ -> 48
+ | No_cmi_file _ -> 49
;;
-let last_warning_number = 48
+let last_warning_number = 49
(* Must be the max number returned by the [number] function. *)
let letter = function
@@ -286,7 +288,7 @@ let message = function
| Unused_argument -> "this argument will not be used by the function."
| Nonreturning_statement ->
"this statement never returns (or has an unsound type.)"
- | Camlp4 s -> s
+ | Preprocessor s -> s
| Useless_record_with ->
"all the fields are explicitly listed in this record:\n\
the 'with' clause is useless."
@@ -320,12 +322,15 @@ let message = function
"constructor " ^ s ^
" is never used to build values.\n\
Its type is exported as a private type."
- | Unused_exception (s, false) ->
- "unused exception constructor " ^ s ^ "."
- | Unused_exception (s, true) ->
- "exception constructor " ^ s ^
- " is never raised or used to build values.\n\
+ | Unused_extension (s, false, false) -> "unused extension constructor " ^ s ^ "."
+ | Unused_extension (s, true, _) ->
+ "extension constructor " ^ s ^
+ " is never used to build values.\n\
(However, this constructor appears in patterns.)"
+ | Unused_extension (s, false, true) ->
+ "extension constructor " ^ s ^
+ " is never used to build values.\n\
+ It is exported or rebound as a private extension."
| Unused_rec_flag ->
"unused rec flag."
| Name_out_of_scope (ty, [nm], false) ->
@@ -366,6 +371,8 @@ let message = function
Printf.sprintf "implicit elimination of optional argument%s %s"
(if List.length sl = 1 then "" else "s")
(String.concat ", " sl)
+ | No_cmi_file s ->
+ "no cmi file was found in path for module " ^ s
;;
let nerrors = ref 0;;
@@ -426,7 +433,7 @@ let descriptions =
19, "Type without principality.";
20, "Unused function argument.";
21, "Non-returning statement.";
- 22, "Camlp4 warning.";
+ 22, "Proprocessor warning.";
23, "Useless record \"with\" clause.";
24, "Bad module name: the source file name is not a valid OCaml module \
name.";
@@ -449,7 +456,7 @@ let descriptions =
35, "Unused for-loop index.";
36, "Unused ancestor variable.";
37, "Unused constructor.";
- 38, "Unused exception constructor.";
+ 38, "Unused extension constructor.";
39, "Unused rec flag.";
40, "Constructor or label name used out of scope.";
41, "Ambiguous constructor or label name.";
@@ -457,9 +464,10 @@ let descriptions =
43, "Nonoptional label applied as optional.";
44, "Open statement shadows an already defined identifier.";
45, "Open statement shadows an already defined label or constructor.";
- 46, "Illegal environment variable";
- 47, "Illegal attribute payload";
- 48, "Implicit elimination of optional arguments";
+ 46, "Illegal environment variable.";
+ 47, "Illegal attribute payload.";
+ 48, "Implicit elimination of optional arguments.";
+ 49, "Absent cmi file when looking up module alias.";
]
;;
diff --git a/utils/warnings.mli b/utils/warnings.mli
index 05bf66bdea..edfd732c31 100644
--- a/utils/warnings.mli
+++ b/utils/warnings.mli
@@ -34,7 +34,7 @@ type t =
| Without_principality of string (* 19 *)
| Unused_argument (* 20 *)
| Nonreturning_statement (* 21 *)
- | Camlp4 of string (* 22 *)
+ | Preprocessor of string (* 22 *)
| Useless_record_with (* 23 *)
| Bad_module_name of string (* 24 *)
| All_clauses_guarded (* 25 *)
@@ -50,7 +50,7 @@ type t =
| Unused_for_index of string (* 35 *)
| Unused_ancestor of string (* 36 *)
| Unused_constructor of string * bool * bool (* 37 *)
- | Unused_exception of string * bool (* 38 *)
+ | Unused_extension of string * 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 *)
@@ -61,6 +61,7 @@ type t =
| Bad_env_variable of string * string (* 46 *)
| Attribute_payload of string * string (* 47 *)
| Eliminated_optional_arguments of string list (* 48 *)
+ | No_cmi_file of string (* 49 *)
;;
val parse_options : bool -> string -> unit;;
diff --git a/yacc/defs.h b/yacc/defs.h
index 0a823874f6..32114ea568 100644
--- a/yacc/defs.h
+++ b/yacc/defs.h
@@ -312,45 +312,45 @@ extern action *add_reductions(int stateno, register action *actions);
extern action *add_reduce(register action *actions, register int ruleno, register int symbol);
extern void closure (short int *nucleus, int n);
extern void create_symbol_table (void);
-extern void default_action_error (void);
+extern void default_action_error (void) Noreturn;
extern void done (int k) Noreturn;
-extern void entry_without_type (char *s);
-extern void fatal (char *msg);
+extern void entry_without_type (char *s) Noreturn;
+extern void fatal (char *msg) Noreturn;
extern void finalize_closure (void);
extern void free_parser (void);
extern void free_symbol_table (void);
extern void free_symbols (void);
-extern void illegal_character (char *c_cptr);
-extern void illegal_token_ref (int i, char *name);
+extern void illegal_character (char *c_cptr) Noreturn;
+extern void illegal_token_ref (int i, char *name) Noreturn;
extern void lalr (void);
extern void lr0 (void);
extern void make_parser (void);
-extern void no_grammar (void);
-extern void no_space (void);
-extern void open_error (char *filename);
+extern void no_grammar (void) Noreturn;
+extern void no_space (void) Noreturn;
+extern void open_error (char *filename) Noreturn;
extern void output (void);
-extern void over_unionized (char *u_cptr);
+extern void over_unionized (char *u_cptr) Noreturn;
extern void prec_redeclared (void);
-extern void polymorphic_entry_point(char *s);
+extern void polymorphic_entry_point(char *s) Noreturn;
extern void reader (void);
extern void reflexive_transitive_closure (unsigned int *R, int n);
extern void reprec_warning (char *s);
extern void retyped_warning (char *s);
extern void revalued_warning (char *s);
extern void set_first_derives (void);
-extern void syntax_error (int st_lineno, char *st_line, char *st_cptr) Noreturn, terminal_lhs (int s_lineno);
-extern void terminal_start (char *s);
-extern void tokenized_start (char *s);
-extern void too_many_entries (void);
+extern void syntax_error (int st_lineno, char *st_line, char *st_cptr) Noreturn, terminal_lhs (int s_lineno) Noreturn;
+extern void terminal_start (char *s) Noreturn;
+extern void tokenized_start (char *s) Noreturn;
+extern void too_many_entries (void) Noreturn;
extern void undefined_goal (char *s);
extern void undefined_symbol (char *s);
-extern void unexpected_EOF (void);
-extern void unknown_rhs (int i);
-extern void unterminated_action (int a_lineno, char *a_line, char *a_cptr);
-extern void unterminated_comment (int c_lineno, char *c_line, char *c_cptr);
-extern void unterminated_string (int s_lineno, char *s_line, char *s_cptr);
-extern void unterminated_text (int t_lineno, char *t_line, char *t_cptr);
-extern void unterminated_union (int u_lineno, char *u_line, char *u_cptr);
-extern void used_reserved (char *s);
+extern void unexpected_EOF (void) Noreturn;
+extern void unknown_rhs (int i) Noreturn;
+extern void unterminated_action (int a_lineno, char *a_line, char *a_cptr) Noreturn;
+extern void unterminated_comment (int c_lineno, char *c_line, char *c_cptr) Noreturn;
+extern void unterminated_string (int s_lineno, char *s_line, char *s_cptr) Noreturn;
+extern void unterminated_text (int t_lineno, char *t_line, char *t_cptr) Noreturn;
+extern void unterminated_union (int u_lineno, char *u_line, char *u_cptr) Noreturn;
+extern void used_reserved (char *s) Noreturn;
extern void verbose (void);
extern void write_section (char **section);
diff --git a/yacc/main.c b/yacc/main.c
index d2f329310d..9388b9d1a8 100644
--- a/yacc/main.c
+++ b/yacc/main.c
@@ -55,11 +55,7 @@ char *text_file_name;
char *union_file_name;
char *verbose_file_name;
-#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__DragonFly__) || (__APPLE__)
-#define HAVE_MKSTEMP
-#endif
-
-#ifdef HAVE_MKSTEMP
+#ifdef HAS_MKSTEMP
int action_fd = -1, entry_fd = -1, text_fd = -1, union_fd = -1;
#endif
@@ -101,7 +97,7 @@ char *rassoc;
short **derives;
char *nullable;
-#if !defined(HAVE_MKSTEMP)
+#if !defined(HAS_MKSTEMP)
extern char *mktemp(char *);
#endif
#ifndef NO_UNIX
@@ -111,7 +107,7 @@ extern char *getenv(const char *);
void done(int k)
{
-#ifdef HAVE_MKSTEMP
+#ifdef HAS_MKSTEMP
if (action_fd != -1)
unlink(action_file_name);
if (entry_fd != -1)
@@ -325,7 +321,7 @@ void create_file_names(void)
text_file_name[len + 5] = 't';
union_file_name[len + 5] = 'u';
-#ifdef HAVE_MKSTEMP
+#ifdef HAS_MKSTEMP
action_fd = mkstemp(action_file_name);
if (action_fd == -1)
open_error(action_file_name);
@@ -384,7 +380,7 @@ void open_files(void)
open_error(input_file_name);
}
-#ifdef HAVE_MKSTEMP
+#ifdef HAS_MKSTEMP
action_file = fdopen(action_fd, "w");
#else
action_file = fopen(action_file_name, "w");
@@ -392,7 +388,7 @@ void open_files(void)
if (action_file == 0)
open_error(action_file_name);
-#ifdef HAVE_MKSTEMP
+#ifdef HAS_MKSTEMP
entry_file = fdopen(entry_fd, "w");
#else
entry_file = fopen(entry_file_name, "w");
@@ -400,7 +396,7 @@ void open_files(void)
if (entry_file == 0)
open_error(entry_file_name);
-#ifdef HAVE_MKSTEMP
+#ifdef HAS_MKSTEMP
text_file = fdopen(text_fd, "w");
#else
text_file = fopen(text_file_name, "w");
@@ -420,7 +416,7 @@ void open_files(void)
defines_file = fopen(defines_file_name, "w");
if (defines_file == 0)
open_error(defines_file_name);
-#ifdef HAVE_MKSTEMP
+#ifdef HAS_MKSTEMP
union_file = fdopen(union_fd, "w");
#else
union_file = fopen(union_file_name, "w");