summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDamien Doligez <damien.doligez-inria.fr>2008-01-11 16:13:18 +0000
committerDamien Doligez <damien.doligez-inria.fr>2008-01-11 16:13:18 +0000
commit9ea5edac9ab0b3860688583a2ff22a9e164be086 (patch)
tree353e23e669026900926bbd60cfc791906887ce63
parentdb2092907f2eddcaf0b72f4bd0f429001364dbe5 (diff)
merge changes 3.10.0 -> 3.10.1
git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@8768 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
-rw-r--r--Changes112
-rw-r--r--Makefile.nt3
-rw-r--r--README.win3211
-rw-r--r--VERSION2
-rw-r--r--asmcomp/amd64/emit.mlp34
-rw-r--r--asmcomp/amd64/emit_nt.mlp2
-rw-r--r--asmcomp/arm/emit.mlp3
-rw-r--r--asmcomp/arm/selection.ml10
-rw-r--r--asmcomp/asmlink.ml18
-rw-r--r--asmcomp/hppa/reload.ml22
-rw-r--r--asmcomp/hppa/selection.ml6
-rw-r--r--asmcomp/i386/emit.mlp12
-rw-r--r--asmcomp/i386/emit_nt.mlp2
-rw-r--r--asmcomp/i386/proc_nt.ml15
-rw-r--r--asmrun/backtrace.c2
-rw-r--r--asmrun/i386.S14
-rw-r--r--asmrun/roots.c20
-rw-r--r--asmrun/signals_osdep.h26
-rwxr-xr-xboot/ocamlcbin1025571 -> 1027220 bytes
-rwxr-xr-xboot/ocamldepbin287005 -> 286762 bytes
-rwxr-xr-xboot/ocamllexbin162183 -> 162443 bytes
-rwxr-xr-xbuild/buildbot6
-rwxr-xr-xbuild/distclean.sh16
-rwxr-xr-xbuild/install.sh14
-rwxr-xr-xbuild/mkmyocamlbuild_config.sh13
-rwxr-xr-xbuild/partial-boot.sh14
-rwxr-xr-xbuild/partial-install.sh13
-rw-r--r--build/targets.sh13
-rw-r--r--bytecomp/matching.ml4
-rw-r--r--bytecomp/translclass.ml31
-rw-r--r--bytecomp/translmod.ml10
-rw-r--r--byterun/compare.c4
-rw-r--r--byterun/finalise.c21
-rw-r--r--byterun/gc_ctrl.c9
-rw-r--r--byterun/intern.c2
-rw-r--r--byterun/ints.c10
-rw-r--r--byterun/io.h2
-rw-r--r--byterun/major_gc.c109
-rw-r--r--byterun/minor_gc.c5
-rw-r--r--camlp4/Camlp4/Printers/OCaml.ml6
-rw-r--r--camlp4/Camlp4/Printers/OCamlr.ml2
-rw-r--r--camlp4/Camlp4/Sig.ml4
-rw-r--r--camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.ml10
-rw-r--r--camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.mli1
-rw-r--r--camlp4/Camlp4/Struct/Lexer.mll1
-rw-r--r--camlp4/Camlp4Bin.ml4
-rw-r--r--camlp4/Camlp4Top/Rprint.ml1
-rw-r--r--config/Makefile.msvc4
-rw-r--r--config/Makefile.msvc644
-rw-r--r--config/auto-aux/stackov.c2
-rwxr-xr-xconfigure16
-rw-r--r--debugger/main.ml1
-rw-r--r--emacs/README10
-rw-r--r--emacs/caml-font-old.el141
-rw-r--r--emacs/caml-font.el215
-rw-r--r--emacs/caml-types.el43
-rw-r--r--myocamlbuild.ml32
-rw-r--r--ocamlbuild/examples/example_with_C/_tags1
-rw-r--r--ocamlbuild/examples/example_with_C/fib.ml5
-rw-r--r--ocamlbuild/examples/example_with_C/fibwrap.c7
-rw-r--r--ocamlbuild/examples/example_with_C/main.c10
-rw-r--r--ocamlbuild/examples/example_with_C/myocamlbuild.ml35
-rw-r--r--ocamlbuild/examples/example_with_C/x.ml1
-rwxr-xr-xocamlbuild/start.sh15
-rw-r--r--ocamldoc/Makefile2
-rw-r--r--ocamldoc/odoc_ocamlhtml.mll78
-rw-r--r--otherlibs/labltk/support/tkthread.ml14
-rw-r--r--otherlibs/labltk/support/tkthread.mli9
-rw-r--r--otherlibs/num/nat_stubs.c4
-rw-r--r--otherlibs/str/str.ml6
-rw-r--r--otherlibs/systhreads/posix.c6
-rw-r--r--otherlibs/systhreads/thread.mli6
-rw-r--r--otherlibs/unix/access.c2
-rw-r--r--otherlibs/unix/signals.c8
-rw-r--r--otherlibs/unix/unix.mli3
-rw-r--r--otherlibs/unix/unixLabels.mli24
-rw-r--r--otherlibs/win32unix/createprocess.c2
-rw-r--r--otherlibs/win32unix/open.c9
-rw-r--r--otherlibs/win32unix/winwait.c4
-rw-r--r--parsing/location.ml27
-rw-r--r--parsing/parser.mly19
-rw-r--r--stdlib/arg.ml13
-rw-r--r--stdlib/arg.mli2
-rw-r--r--stdlib/camlinternalMod.ml12
-rw-r--r--stdlib/camlinternalOO.ml2
-rw-r--r--stdlib/format.ml985
-rw-r--r--stdlib/int32.mli8
-rw-r--r--stdlib/int64.mli8
-rw-r--r--stdlib/printf.mli13
-rw-r--r--test/Moretest/recmod.ml145
-rw-r--r--testlabl/bugs/pr4435.ml11
-rw-r--r--tools/depend.ml4
-rwxr-xr-xtools/make-package-macosx8
-rw-r--r--typing/btype.ml10
-rw-r--r--typing/ctype.ml54
-rw-r--r--typing/includemod.ml5
-rw-r--r--typing/oprint.ml2
-rw-r--r--typing/parmatch.ml23
-rw-r--r--typing/printtyp.ml2
-rw-r--r--typing/subst.ml2
-rw-r--r--typing/subst.mli3
-rw-r--r--typing/typeclass.ml9
-rw-r--r--typing/typecore.ml84
-rw-r--r--typing/typecore.mli2
-rw-r--r--typing/typedtree.ml4
-rw-r--r--typing/typedtree.mli4
-rw-r--r--typing/typemod.ml123
-rw-r--r--typing/types.ml2
-rw-r--r--typing/types.mli2
-rw-r--r--typing/typetexp.ml69
-rw-r--r--utils/ccomp.ml4
-rw-r--r--utils/ccomp.mli1
112 files changed, 1837 insertions, 1183 deletions
diff --git a/Changes b/Changes
index 4b97f56eb..f73a3076e 100644
--- a/Changes
+++ b/Changes
@@ -17,18 +17,110 @@ Compilers:
- Check that at most one of -pack, -a, -shared, -c, -output-obj is given on the
command line.
- Revised -output-obj: the output name must now be provided; its extension must
- be one of $(EXT_OBJ), $(EXT_DLL) (or .c for the bytecode compiler). The compilers
- can now produce a shared library (with all the needed -ccopts/-ccobjs options) directly.
-- The -dllib options recorded in libraries are no longer ignored when -use_runtime or -use_prims is used
- (unless -no_auto_link is explicitly used).
+ be one of $(EXT_OBJ), $(EXT_DLL) (or .c for the bytecode compiler). The
+ compilers can now produce a shared library (with all the needed
+ -ccopts/-ccobjs options) directly.
+- The -dllib options recorded in libraries are no longer ignored when
+ -use_runtime or -use_prims is used (unless -no_auto_link is explicitly used).
Native-code compiler:
-- A new option "-shared" to produce a plugin that can be dynlinked with the native version of Dynlink.
-- A new option "-dlcode" to produce code that can be put in a plugin (needed for some platforms only).
+- A new option "-shared" to produce a plugin that can be dynlinked with the
+ native version of Dynlink.
+- A new option "-dlcode" to produce code that can be put in a plugin (needed
+ for some platforms only).
Other libraries:
-- On some platforms, the dynlink library is now available in native code. A new Boolean
- Dynlink.is_native allows the program to know whether it has been compiled in bytecode or in native code.
+- On some platforms, the dynlink library is now available in native code. A
+ new Boolean Dynlink.is_native allows the program to know whether it has
+ been compiled in bytecode or in native code.
+
+
+Objective Caml 3.10.1:
+----------------------
+
+Bug fixes:
+- PR#3830 small bugs in docs
+- PR#4053 compilers: improved compilation time for large variant types
+- PR#4174 ocamlopt: fixed ocamlopt -nopervasives
+- PR#4199 otherlibs: documented a small problem in Unix.utimes
+- PR#4280 camlp4: parsing of identifier (^)
+- PR#4281 camlp4: parsing of type constraint
+- PR#4285 runtime: cannot compile under AIX
+- PR#4286 ocamlbuild: cannot compile under AIX and SunOS
+- PR#4288 compilers: including a functor application with side effects
+- PR#4295 camlp4 toplevel: synchronization after an error
+- PR#4300 ocamlopt: crash with backtrace and illegal array access
+- PR#4302 camlp4: list comprehension parsing problem
+- PR#4304 ocamlbuild: handle -I correctly
+- PR#4305 stdlib: alignment of Arg.Symbol
+- PR#4307 camlp4: assertion failure
+- PR#4312 camlp4: accept "let _ : int = 1"
+- PR#4313 ocamlbuild: -log and missing directories
+- PR#4315 camlp4: constraints in classes
+- PR#4316 compilers: crash with recursive modules and Lazy
+- PR#4318 ocamldoc: installation problem with Cygwin (tentative fix)
+- PR#4322 ocamlopt: stack overflow under Windows
+- PR#4325 compilers: wrong error message for unused var
+- PR#4326 otherlibs: marshal Big_int on win64
+- PR#4327 ocamlbuild: make emacs look for .annot in _build directory
+- PR#4328 camlp4: stack overflow with nil nodes
+- PR#4331 camlp4: guards on fun expressions
+- PR#4332 camlp4: parsing of negative 32/64 bit numbers
+- PR#4336 compilers: unsafe recursive modules
+- PR#4337 (note) camlp4: invalid character escapes
+- PR#4339 ocamlopt: problems on HP-UX (tentative fix)
+- PR#4340 camlp4: wrong pretty-printing of optional arguments
+- PR#4348 ocamlopt: crash on Mac Intel
+- PR#4349 camlp4: bug in private type definitions
+- PR#4350 compilers: type errors with records and polymorphic variants
+- PR#4352 compilers: terminal recursion under Windows (tentative fix)
+- PR#4354 ocamlcp: mismatch with ocaml on polymorphic let
+- PR#4358 ocamlopt: float constants wrong on ARM
+- PR#4360 ocamldoc: string inside comment
+- PR#4365 toplevel: wrong pretty-printing of polymorphic variants
+- PR#4373 otherlibs: leaks in win32unix
+- PR#4374 otherlibs: threads module not initialized
+- PR#4375 configure: fails to build on bytecode-only architectures
+- PR#4377 runtime: finalisation of infix pointers
+- PR#4378 ocamlbuild: typo in plugin.ml
+- PR#4379 ocamlbuild: problem with plugins under Windows
+- PR#4382 compilers: typing of polymorphic record fields
+- PR#4383 compilers: including module with private type
+- PR#4385 stdlib: Int32/Int64.format are unsafe
+- PR#4386 otherlibs: wrong signal numbers with Unix.sigprocmask etc.
+- PR#4387 ocamlbuild: build directory not used properly
+- PR#4392 ocamldep: optional argument of class
+- PR#4394 otherlibs: infinite loops in Str
+- PR#4397 otherlibs: wrong size for flag arrays in win32unix
+- PR#4402 ocamldebug: doesn't work with -rectypes
+- PR#4410 ocamlbuild: problem with plugin and -build
+- PR#4411 otherlibs: crash with Unix.access under Windows
+- PR#4412 stdlib: marshalling broken on 64 bit architectures
+- PR#4413 ocamlopt: crash on AMD64 with out-of-bound access and reraise
+- PR#4417 camlp4: pretty-printing of unary minus
+- PR#4419 camlp4: problem with constraint in type class
+- PR#4426 compilers: problem with optional labels
+- PR#4427 camlp4: wrong pretty-printing of lists of functions
+- PR#4433 ocamlopt: fails to build on MacOSX 10.5
+- PR#4435 compilers: crash with objects
+- PR#4439 fails to build on MacOSX 10.5
+- PR#4441 crash when build on sparc64 linux
+- PR#4442 stdlib: crash with weak pointers
+- PR#4446 configure: fails to detect X11 on MacOSX 10.5
+- PR#4448 runtime: huge page table on 64-bit architectures
+- PR#4450 compilers: stack overflow with recursive modules
+- PR#4470 compilers: type-checking of recursive modules too restrictive
+- PR#4472 configure: autodetection of libX11.so on Fedora x86_64
+- printf: removed (partially implemented) positional specifications
+- polymorphic < and <= comparisons: some C compiler optimizations
+ were causing incorrect results when arguments are incomparable
+
+New features:
+- made configure script work on PlayStation 3
+- ARM port: brought up-to-date for Debian 4.0 (Etch)
+- many other small changes and bugfixes in camlp4, ocamlbuild, labltk,
+ emacs files,
+
Objective Caml 3.10.0:
----------------------
@@ -2184,4 +2276,8 @@ Caml Special Light 1.06:
* First public release.
+<<<<<<< Changes
+$Id$
+=======
$Id$
+>>>>>>> 1.168.2.7
diff --git a/Makefile.nt b/Makefile.nt
index 349e2158c..4351e14b7 100644
--- a/Makefile.nt
+++ b/Makefile.nt
@@ -28,7 +28,8 @@ CAMLDEP=boot/ocamlrun tools/ocamldep
DEPFLAGS=$(INCLUDES)
CAMLRUN=byterun/ocamlrun
-INCLUDES=-I utils -I parsing -I typing -I bytecomp -I asmcomp -I driver -I toplevel
+INCLUDES=-I utils -I parsing -I typing -I bytecomp -I asmcomp -I driver \
+ -I toplevel
UTILS=utils/misc.cmo utils/tbl.cmo utils/config.cmo \
utils/clflags.cmo utils/terminfo.cmo utils/ccomp.cmo utils/warnings.cmo \
diff --git a/README.win32 b/README.win32
index c94f30a4a..bfdff2b04 100644
--- a/README.win32
+++ b/README.win32
@@ -89,8 +89,11 @@ THIRD-PARTY SOFTWARE:
the Microsoft Windows Server 2003 SP1 Platform SDK, which can
be downloaded for free from http://www.microsoft.com/.
-[3] MASM version 6.11 or later. MASM can be
- downloaded for free from Microsoft's Web site; for directions, see
+[3] MASM version 6.11 or later. The full distribution of Visual C++ 2005
+ contains MASM version 8. Users of the Express Edition of Visual C++
+ 2005 can download MASM version 8 from
+http://www.microsoft.com/downloads/details.aspx?FamilyID=7A1C9DA0-0510-44A2-B042-7EF370530C64&displaylang=en
+ To obtain MASM version 6.11, see
http://users.easystreet.com/jkirwan/new/pctools.html.
[4] TCL/TK version 8.4. Windows binaries are available as part of the
@@ -103,7 +106,7 @@ distribution (ocaml-X.YZ.tar.gz), which also contains the files modified
for Windows.
You will need the following software components to perform the recompilation:
-- Windows NT, 2000, or XP.
+- Windows NT, 2000, XP, or Vista.
- Items [1], [2], [3] and [4] from the list of recommended software above.
- The Cygwin port of GNU tools, available from http://www.cygwin.com/
@@ -205,7 +208,7 @@ environment variable. E.g. if Tcl/Tk was installed in C:\tcl, add
RECOMPILATION FROM THE SOURCES:
You will need the following software components to perform the recompilation:
-- Windows NT, 2000, or XP.
+- Windows NT, 2000, XP, or Vista.
- Cygwin: http://sourceware.cygnus.com/cygwin/
- TCL/TK version 8.4 (see above).
diff --git a/VERSION b/VERSION
index a4ebbac79..b8a624643 100644
--- a/VERSION
+++ b/VERSION
@@ -1,4 +1,4 @@
-3.11+dev8 Private_abbrevs+natdynlink (2007-12-04)
+3.11+dev9 Private_abbrevs+natdynlink (2008-01-10)
# 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/amd64/emit.mlp b/asmcomp/amd64/emit.mlp
index 215cec326..ec021ca35 100644
--- a/asmcomp/amd64/emit.mlp
+++ b/asmcomp/amd64/emit.mlp
@@ -36,10 +36,10 @@ let frame_required () =
let frame_size () = (* includes return address *)
if frame_required() then begin
- let sz =
+ let sz =
(!stack_offset + 8 * (num_stack_slots.(0) + num_stack_slots.(1)) + 8)
in Misc.align sz 16
- end else
+ end else
!stack_offset + 8
let slot_offset loc cl =
@@ -69,7 +69,7 @@ let emit_jump s =
let load_symbol_addr s =
if !Clflags.dlcode
then `movq {emit_symbol s}@GOTPCREL(%rip)`
- else if !pic_code
+ else if !pic_code
then `leaq {emit_symbol s}(%rip)`
else `movq ${emit_symbol s}`
@@ -216,7 +216,7 @@ let emit_call_bound_error bd =
let emit_call_bound_errors () =
List.iter emit_call_bound_error !bound_error_sites;
if !bound_error_call > 0 then
- `{emit_label !bound_error_call}: {emit_jump "caml_ml_array_bound_error"}\n`
+ `{emit_label !bound_error_call}: {emit_call "caml_ml_array_bound_error"}\n`
(* Names for instructions *)
@@ -360,7 +360,7 @@ let emit_instr fallthrough i =
` jmp {emit_label !tailrec_entry_point}\n`
else begin
output_epilogue();
- ` {emit_jump s}\n`
+ ` {emit_jump s}\n`
end
| Lop(Iextcall(s, alloc)) ->
if alloc then begin
@@ -417,10 +417,10 @@ let emit_instr fallthrough i =
if !fastcode_flag then begin
let lbl_redo = new_label() in
`{emit_label lbl_redo}: subq ${emit_int n}, %r15\n`;
- if !Clflags.dlcode then begin
+ if !Clflags.dlcode then begin
` {load_symbol_addr "caml_young_limit"}, %rax\n`;
` cmpq (%rax), %r15\n`;
- end else
+ end else
` cmpq {emit_symbol "caml_young_limit"}(%rip), %r15\n`;
let lbl_call_gc = new_label() in
let lbl_frame = record_frame_label i.live Debuginfo.none in
@@ -534,7 +534,7 @@ let emit_instr fallthrough i =
` cmpq {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`;
let b = name_for_cond_branch cmp in
` j{emit_string b} {emit_label lbl}\n`
- | Iinttest_imm((Isigned Ceq | Isigned Cne |
+ | Iinttest_imm((Isigned Ceq | Isigned Cne |
Iunsigned Ceq | Iunsigned Cne) as cmp, 0) ->
output_test_zero i.arg.(0);
let b = name_for_cond_branch cmp in
@@ -569,8 +569,22 @@ let emit_instr fallthrough i =
| Lswitch jumptbl ->
let lbl = new_label() in
if !pic_code || !Clflags.dlcode then begin
- ` leaq {emit_label lbl}(%rip), %r11\n`;
- ` jmp *(%r11, {emit_reg i.arg.(0)}, 8)\n`
+ (* PR#4424: r11 is known to be clobbered by the Lswitch,
+ meaning that no variable that is live across the Lswitch
+ is assigned to r11. However, the argument to Lswitch
+ can still be assigned to r11, so we need to special-case
+ this situation. *)
+ if i.arg.(0).loc = Reg 9 (* ie r11, cf amd64/proc.ml *) then begin
+ ` salq $3, %r11\n`;
+ ` pushq %r11\n`;
+ ` leaq {emit_label lbl}(%rip), %r11\n`;
+ ` addq 0(%rsp), %r11\n`;
+ ` addq $8, %rsp\n`;
+ ` jmp *(%r11)\n`
+ end else begin
+ ` leaq {emit_label lbl}(%rip), %r11\n`;
+ ` jmp *(%r11, {emit_reg i.arg.(0)}, 8)\n`
+ end
end else begin
` jmp *{emit_label lbl}(, {emit_reg i.arg.(0)}, 8)\n`
end;
diff --git a/asmcomp/amd64/emit_nt.mlp b/asmcomp/amd64/emit_nt.mlp
index 30b046e6d..71b71157b 100644
--- a/asmcomp/amd64/emit_nt.mlp
+++ b/asmcomp/amd64/emit_nt.mlp
@@ -217,7 +217,7 @@ let emit_call_bound_error bd =
let emit_call_bound_errors () =
List.iter emit_call_bound_error !bound_error_sites;
if !bound_error_call > 0 then
- `{emit_label !bound_error_call}: jmp caml_ml_array_bound_error\n`
+ `{emit_label !bound_error_call}: call caml_ml_array_bound_error\n`
(* Names for instructions *)
diff --git a/asmcomp/arm/emit.mlp b/asmcomp/arm/emit.mlp
index a26aaee61..586d477bd 100644
--- a/asmcomp/arm/emit.mlp
+++ b/asmcomp/arm/emit.mlp
@@ -648,9 +648,6 @@ let begin_assembly() =
`trap_ptr .req r11\n`;
`alloc_ptr .req r8\n`;
`alloc_limit .req r9\n`;
- `sp .req r13\n`;
- `lr .req r14\n`;
- `pc .req r15\n`;
let lbl_begin = Compilenv.make_symbol (Some "data_begin") in
` .data\n`;
` .global {emit_symbol lbl_begin}\n`;
diff --git a/asmcomp/arm/selection.ml b/asmcomp/arm/selection.ml
index 3066d785d..e34093acb 100644
--- a/asmcomp/arm/selection.ml
+++ b/asmcomp/arm/selection.ml
@@ -106,7 +106,7 @@ method select_operation op args =
| _ ->
(Iextcall("__modsi3", false), args)
end
- | Ccheckbound ->
+ | Ccheckbound _ ->
begin match args with
[Cop(Clsr, [arg1; Cconst_int n]); arg2]
when n > 0 && n < 32 && not(is_intconst arg2) ->
@@ -116,15 +116,15 @@ method select_operation op args =
end
| _ -> super#select_operation op args
-(* In mul rd, rm, rs, rm and rd must be different.
+(* In mul rd, rm, rs, the registers rm and rd must be different.
We deal with this by pretending that rm is also a result of the mul
operation. *)
-method insert_op op rs rd =
+method insert_op_debug op dbg rs rd =
if op = Iintop(Imul) then begin
- self#insert (Iop op) rs [| rd.(0); rs.(0) |]; rd
+ self#insert_debug (Iop op) dbg rs [| rd.(0); rs.(0) |]; rd
end else
- super#insert_op op rs rd
+ super#insert_op_debug op dbg rs rd
end
diff --git a/asmcomp/asmlink.ml b/asmcomp/asmlink.ml
index 8abc43908..e406d35a6 100644
--- a/asmcomp/asmlink.ml
+++ b/asmcomp/asmlink.ml
@@ -163,7 +163,7 @@ let read_file obj_name =
let infos =
try Compilenv.read_library_info file_name
with Compilenv.Error(Not_a_unit_info _) ->
- raise(Error(Not_an_object_file file_name))
+ raise(Error(Not_an_object_file file_name))
in
Library (file_name,infos)
end
@@ -172,17 +172,17 @@ let read_file obj_name =
let scan_file obj_name tolink = match read_file obj_name with
| Unit (file_name,info,crc) ->
(* This is a .cmx file. It must be linked in any case.
- Read the infos to see which modules it requires. *)
+ Read the infos to see which modules it requires. *)
let (info, crc) = Compilenv.read_unit_info file_name in
remove_required info.ui_name;
List.iter (add_required file_name) info.ui_imports_cmx;
(info, file_name, crc) :: tolink
| Library (file_name,infos) ->
(* This is an archive file. Each unit contained in it will be linked
- in only if needed. *)
+ in only if needed. *)
add_ccobjs infos;
List.fold_right
- (fun (info, crc) reqd ->
+ (fun (info, crc) reqd ->
if info.ui_force_link
|| !Clflags.link_everything
|| is_required info.ui_name
@@ -194,7 +194,7 @@ let scan_file obj_name tolink = match read_file obj_name with
(info, file_name, crc) :: reqd
end else
reqd)
- infos.lib_units tolink
+ infos.lib_units tolink
(* Second pass: generate the startup file and link it with everything else *)
@@ -219,8 +219,8 @@ let make_startup_file ppf filename units_list =
(List.map
(fun (unit,_,crc) ->
try (unit.ui_name, List.assoc unit.ui_name unit.ui_imports_cmi,
- crc,
- unit.ui_defines)
+ crc,
+ unit.ui_defines)
with Not_found -> assert false)
units_list));
compile_phrase(Cmmgen.data_segment_table ("_startup" :: name_list));
@@ -278,7 +278,9 @@ let link_shared ppf objfiles output_name =
remove_file startup_obj
let call_linker file_list startup_file output_name =
- let main_dll = !Clflags.output_c_object && Filename.check_suffix output_name Config.ext_dll in
+ let main_dll = !Clflags.output_c_object
+ && Filename.check_suffix output_name Config.ext_dll
+ in
let files = startup_file :: (List.rev file_list) in
let files, c_lib =
if (not !Clflags.output_c_object) || main_dll then
diff --git a/asmcomp/hppa/reload.ml b/asmcomp/hppa/reload.ml
index 57a242d70..54208fcc3 100644
--- a/asmcomp/hppa/reload.ml
+++ b/asmcomp/hppa/reload.ml
@@ -14,5 +14,25 @@
(* Reloading for the HPPA *)
+
+open Cmm
+open Arch
+open Reg
+open Mach
+open Proc
+
+class reload = object (self)
+
+inherit Reloadgen.reload_generic as super
+
+method reload_operation op arg res =
+ match op with
+ Iintop(Idiv | Imod)
+ | Iintop_imm((Idiv | Imod), _) -> (arg, res)
+ | _ -> super#reload_operation op arg res
+end
+
+
+
let fundecl f =
- (new Reloadgen.reload_generic)#fundecl f
+ (new reload)#fundecl f
diff --git a/asmcomp/hppa/selection.ml b/asmcomp/hppa/selection.ml
index 24db6cd90..6a0e9fe40 100644
--- a/asmcomp/hppa/selection.ml
+++ b/asmcomp/hppa/selection.ml
@@ -92,17 +92,17 @@ method select_operation op args =
(* Deal with register constraints *)
-method insert_op op rs rd =
+method insert_op_debug op dbg rs rd =
match op with
Iintop(Idiv | Imod) -> (* handled via calls to millicode *)
let rs' = [|phys_reg 20; phys_reg 19|] (* %r26, %r25 *)
and rd' = [|phys_reg 22|] (* %r29 *) in
self#insert_moves rs rs';
- self#insert (Iop op) rs' rd';
+ self#insert_debug (Iop op) dbg rs' rd';
self#insert_moves rd' rd;
rd
| _ ->
- super#insert_op op rs rd
+ super#insert_op_debug op dbg rs rd
end
diff --git a/asmcomp/i386/emit.mlp b/asmcomp/i386/emit.mlp
index b50ecff27..fe1291e02 100644
--- a/asmcomp/i386/emit.mlp
+++ b/asmcomp/i386/emit.mlp
@@ -35,7 +35,7 @@ let stack_offset = ref 0
(* Layout of the stack frame *)
let frame_size () = (* includes return address *)
- let sz =
+ let sz =
!stack_offset + 4 * num_stack_slots.(0) + 8 * num_stack_slots.(1) + 4
in Misc.align sz stack_alignment
@@ -116,12 +116,12 @@ let emit_align =
(fun n -> ` .align {emit_int n}\n`)
| _ ->
(fun n -> ` .align {emit_int(Misc.log2 n)}\n`)
-
+
let emit_Llabel fallthrough lbl =
if not fallthrough && !fastcode_flag then
emit_align 16 ;
emit_label lbl
-
+
(* Output a pseudo-register *)
let emit_reg = function
@@ -239,7 +239,7 @@ let emit_call_bound_error bd =
let emit_call_bound_errors () =
List.iter emit_call_bound_error !bound_error_sites;
if !bound_error_call > 0 then
- `{emit_label !bound_error_call}: jmp {emit_symbol "caml_ml_array_bound_error"}\n`
+ `{emit_label !bound_error_call}: call {emit_symbol "caml_ml_array_bound_error"}\n`
(* Names for instructions *)
@@ -299,7 +299,7 @@ let name_for_cond_branch = function
| Iunsigned Ceq -> "e" | Iunsigned Cne -> "ne"
| Iunsigned Cle -> "be" | Iunsigned Cgt -> "a"
| Iunsigned Clt -> "b" | Iunsigned Cge -> "ae"
-
+
(* Output an = 0 or <> 0 test. *)
let output_test_zero arg =
@@ -737,7 +737,7 @@ let emit_instr fallthrough i =
` cmpl {emit_reg i.arg.(1)}, {emit_reg i.arg.(0)}\n`;
let b = name_for_cond_branch cmp in
` j{emit_string b} {emit_label lbl}\n`
- | Iinttest_imm((Isigned Ceq | Isigned Cne |
+ | Iinttest_imm((Isigned Ceq | Isigned Cne |
Iunsigned Ceq | Iunsigned Cne) as cmp, 0) ->
output_test_zero i.arg.(0);
let b = name_for_cond_branch cmp in
diff --git a/asmcomp/i386/emit_nt.mlp b/asmcomp/i386/emit_nt.mlp
index bba42fe88..e4ac9d408 100644
--- a/asmcomp/i386/emit_nt.mlp
+++ b/asmcomp/i386/emit_nt.mlp
@@ -206,7 +206,7 @@ let emit_call_bound_error bd =
let emit_call_bound_errors () =
List.iter emit_call_bound_error !bound_error_sites;
if !bound_error_call > 0 then
- `{emit_label !bound_error_call}: jmp _caml_ml_array_bound_error\n`
+ `{emit_label !bound_error_call}: call _caml_ml_array_bound_error\n`
(* Names for instructions *)
diff --git a/asmcomp/i386/proc_nt.ml b/asmcomp/i386/proc_nt.ml
index fa9d60590..03b5a2f6b 100644
--- a/asmcomp/i386/proc_nt.ml
+++ b/asmcomp/i386/proc_nt.ml
@@ -88,12 +88,23 @@ let word_addressed = false
(* Calling conventions *)
+(* To supplement the processor's meagre supply of registers, we also
+ use some global memory locations to pass arguments beyond the 6th.
+ These globals are denoted by Incoming and Outgoing stack locations
+ with negative offsets, starting at -64.
+ Unlike arguments passed on stack, arguments passed in globals
+ do not prevent tail-call elimination. The caller stores arguments
+ in these globals immediately before the call, and the first thing the
+ callee does is copy them to registers or stack locations.
+ Neither GC nor thread context switches can occur between these two
+ times. *)
+
let calling_conventions first_int last_int first_float last_float make_stack
arg =
let loc = Array.create (Array.length arg) Reg.dummy in
let int = ref first_int in
let float = ref first_float in
- let ofs = ref 0 in
+ let ofs = ref (-64) in
for i = 0 to Array.length arg - 1 do
match arg.(i).typ with
Int | Addr as ty ->
@@ -113,7 +124,7 @@ let calling_conventions first_int last_int first_float last_float make_stack
ofs := !ofs + size_float
end
done;
- (loc, !ofs)
+ (loc, max 0 !ofs)
let incoming ofs = Incoming ofs
let outgoing ofs = Outgoing ofs
diff --git a/asmrun/backtrace.c b/asmrun/backtrace.c
index 50af17bb7..0d918b142 100644
--- a/asmrun/backtrace.c
+++ b/asmrun/backtrace.c
@@ -59,8 +59,8 @@ void caml_stash_backtrace(value exn, uintnat pc, char * sp, char * trapsp)
h = Hash_retaddr(pc);
while(1) {
d = caml_frame_descriptors[h];
+ if (d == 0) return; /* can happen if some code not compiled with -g */
if (d->retaddr == pc) break;
- if (d->retaddr == 0) return; /* should not happen */
h = (h+1) & caml_frame_descriptors_mask;
}
/* Skip to next frame */
diff --git a/asmrun/i386.S b/asmrun/i386.S
index 9d45f6e97..ce05744a7 100644
--- a/asmrun/i386.S
+++ b/asmrun/i386.S
@@ -384,9 +384,17 @@ G(caml_ml_array_bound_error):
ffree %st(5)
ffree %st(6)
ffree %st(7)
- /* Branch to [caml_array_bound_error] */
- movl $ G(caml_array_bound_error), %eax
- jmp G(caml_c_call)
+ /* Record lowest stack address and return address */
+ movl (%esp), %edx
+ 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
+ andl $-16, %esp
+#endif
+ /* Branch to [caml_array_bound_error] (never returns) */
+ call G(caml_array_bound_error)
.data
.globl G(caml_system__frametable)
diff --git a/asmrun/roots.c b/asmrun/roots.c
index 4a4ade47e..46faafc84 100644
--- a/asmrun/roots.c
+++ b/asmrun/roots.c
@@ -43,7 +43,7 @@ int caml_frame_descriptors_mask;
typedef struct link {
void *data;
struct link *next;
-} link;
+} link;
static link *cons(void *data, link *tl) {
link *lnk = caml_stat_alloc(sizeof(link));
@@ -79,13 +79,13 @@ void caml_init_frame_descriptors(void)
link *lnk;
static int inited = 0;
-
+
if (!inited) {
for (i = 0; caml_frametable[i] != 0; i++)
caml_register_frametable(caml_frametable[i]);
inited = 1;
}
-
+
/* Count the frame descriptors */
num_descr = 0;
iter_list(frametables,lnk) {
@@ -111,14 +111,14 @@ void caml_init_frame_descriptors(void)
for (j = 0; j < len; j++) {
h = Hash_retaddr(d->retaddr);
while (caml_frame_descriptors[h] != NULL) {
- h = (h+1) & caml_frame_descriptors_mask;
+ h = (h+1) & caml_frame_descriptors_mask;
}
caml_frame_descriptors[h] = d;
nextd =
- ((uintnat)d +
- sizeof(char *) + sizeof(short) + sizeof(short) +
- sizeof(short) * d->num_live + sizeof(frame_descr *) - 1)
- & -sizeof(frame_descr *);
+ ((uintnat)d +
+ sizeof(char *) + sizeof(short) + sizeof(short) +
+ sizeof(short) * d->num_live + sizeof(frame_descr *) - 1)
+ & -sizeof(frame_descr *);
if (d->frame_size & 1) nextd += 8;
d = (frame_descr *) nextd;
}
@@ -148,7 +148,11 @@ void caml_oldify_local_roots (void)
frame_descr * d;
uintnat h;
int i, j, n, ofs;
+#ifdef Stack_grows_upwards
+ short * p; /* PR#4339: stack offsets are negative in this case */
+#else
unsigned short * p;
+#endif
value glob;
value * root;
struct global_root * gr;
diff --git a/asmrun/signals_osdep.h b/asmrun/signals_osdep.h
index 09dfb4c9e..0ae285f32 100644
--- a/asmrun/signals_osdep.h
+++ b/asmrun/signals_osdep.h
@@ -87,11 +87,12 @@
sigact.sa_flags = SA_SIGINFO
#include <sys/ucontext.h>
+ #include <AvailabilityMacros.h>
- #ifdef _STRUCT_X86_EXCEPTION_STATE32
- #define CONTEXT_REG(r) __##r
- #else
+#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define CONTEXT_REG(r) r
+ #else
+ #define CONTEXT_REG(r) __##r
#endif
#define CONTEXT_STATE (((ucontext_t *)context)->uc_mcontext->CONTEXT_REG(ss))
@@ -123,29 +124,30 @@
static void name(int sig, siginfo_t * info, void * context)
#include <sys/ucontext.h>
-
+ #include <AvailabilityMacros.h>
+
#ifdef __LP64__
#define SET_SIGACT(sigact,name) \
sigact.sa_sigaction = (name); \
sigact.sa_flags = SA_SIGINFO | SA_64REGSET
-
+
typedef unsigned long long context_reg;
-
+
#define CONTEXT_MCONTEXT (((ucontext64_t *)context)->uc_mcontext64)
#else
#define SET_SIGACT(sigact,name) \
sigact.sa_sigaction = (name); \
sigact.sa_flags = SA_SIGINFO
-
+
typedef unsigned long context_reg;
-
+
#define CONTEXT_MCONTEXT (((ucontext_t *)context)->uc_mcontext)
#endif
-
- #ifdef _STRUCT_PPC_EXCEPTION_STATE
- #define CONTEXT_REG(r) __##r
- #else
+
+#if !defined(MAC_OS_X_VERSION_10_5) || MAC_OS_X_VERSION_MIN_REQUIRED < MAC_OS_X_VERSION_10_5
#define CONTEXT_REG(r) r
+ #else
+ #define CONTEXT_REG(r) __##r
#endif
#define CONTEXT_STATE (CONTEXT_MCONTEXT->CONTEXT_REG(ss))
diff --git a/boot/ocamlc b/boot/ocamlc
index 7aa072450..54149e4c7 100755
--- a/boot/ocamlc
+++ b/boot/ocamlc
Binary files differ
diff --git a/boot/ocamldep b/boot/ocamldep
index b959751d1..86a6d5a5b 100755
--- a/boot/ocamldep
+++ b/boot/ocamldep
Binary files differ
diff --git a/boot/ocamllex b/boot/ocamllex
index cc2c60604..9eeea0fdf 100755
--- a/boot/ocamllex
+++ b/boot/ocamllex
Binary files differ
diff --git a/build/buildbot b/build/buildbot
index c755852fe..e9b2579eb 100755
--- a/build/buildbot
+++ b/build/buildbot
@@ -1,5 +1,9 @@
#!/bin/sh
+# If you want to help me by participating to the build/test effort:
+# http://gallium.inria.fr/~pouillar/ocaml-testing.html
+# -- Nicolas Pouillard
+
usage() {
echo "Usage: $0 (make|ocb|ocamlbuild) (win (mingw|msvc|msvc64) | <configure-arg>*)"
exit 1
@@ -11,7 +15,7 @@ finish() {
curl -s -0 -F "log=@$logfile" \
-F "host=`hostname`" \
-F "mode=$mode-$opt_win-$opt_win2" \
- http://weblog.feydakins.org/dropbox || :
+ http://buildbot.feydakins.org/dropbox || :
}
rm -f buildbot.failed
diff --git a/build/distclean.sh b/build/distclean.sh
index 92ced8862..1a88138d8 100755
--- a/build/distclean.sh
+++ b/build/distclean.sh
@@ -1,5 +1,19 @@
#!/bin/sh
+
+#########################################################################
+# #
+# Objective Caml #
+# #
+# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt #
+# #
+# Copyright 2007 Institut National de Recherche en Informatique et #
+# en Automatique. All rights reserved. This file is distributed #
+# under the terms of the Q Public License version 1.0. #
+# #
+#########################################################################
+
# $Id$
+
cd `dirname $0`/..
set -ex
(cd byterun && make clean) || :
@@ -18,7 +32,7 @@ rm -f driver/main.byte driver/optmain.byte lex/main.byte \
camlp4/build/location.mli \
tools/myocamlbuild_config.ml camlp4/build/linenum.mli \
camlp4/build/linenum.mll \
- camlp4/build/terminfo.mli camlp4/build/terminfo.ml
+ camlp4/build/terminfo.mli camlp4/build/terminfo.ml
# from ocamlbuild bootstrap
rm -f ocamlbuild/_log ocamlbuild/,ocamlbuild.byte.start \
diff --git a/build/install.sh b/build/install.sh
index 4f1e829d8..6da2745c7 100755
--- a/build/install.sh
+++ b/build/install.sh
@@ -1,5 +1,19 @@
#!/bin/sh
+
+#########################################################################
+# #
+# Objective Caml #
+# #
+# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt #
+# #
+# Copyright 2007 Institut National de Recherche en Informatique et #
+# en Automatique. All rights reserved. This file is distributed #
+# under the terms of the Q Public License version 1.0. #
+# #
+#########################################################################
+
# $Id$
+
set -e
cd `dirname $0`/..
diff --git a/build/mkmyocamlbuild_config.sh b/build/mkmyocamlbuild_config.sh
index 658f065ff..e48f5b0e0 100755
--- a/build/mkmyocamlbuild_config.sh
+++ b/build/mkmyocamlbuild_config.sh
@@ -1,4 +1,17 @@
#!/bin/sh
+
+#########################################################################
+# #
+# Objective Caml #
+# #
+# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt #
+# #
+# Copyright 2007 Institut National de Recherche en Informatique et #
+# en Automatique. All rights reserved. This file is distributed #
+# under the terms of the Q Public License version 1.0. #
+# #
+#########################################################################
+
# $Id$
cd `dirname $0`/..
diff --git a/build/partial-boot.sh b/build/partial-boot.sh
index 7a10d5480..ee6676ead 100755
--- a/build/partial-boot.sh
+++ b/build/partial-boot.sh
@@ -1,5 +1,19 @@
#!/bin/sh
+
+#########################################################################
+# #
+# Objective Caml #
+# #
+# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt #
+# #
+# Copyright 2007 Institut National de Recherche en Informatique et #
+# en Automatique. All rights reserved. This file is distributed #
+# under the terms of the Q Public License version 1.0. #
+# #
+#########################################################################
+
# $Id$
+
set -ex
cd `dirname $0`/..
OCAMLBUILD_PARTIAL="true"
diff --git a/build/partial-install.sh b/build/partial-install.sh
index f0226e6d9..619976289 100755
--- a/build/partial-install.sh
+++ b/build/partial-install.sh
@@ -1,4 +1,17 @@
#!/bin/sh
+
+#########################################################################
+# #
+# Objective Caml #
+# #
+# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt #
+# #
+# Copyright 2007 Institut National de Recherche en Informatique et #
+# en Automatique. All rights reserved. This file is distributed #
+# under the terms of the Q Public License version 1.0. #
+# #
+#########################################################################
+
# $Id$
######################################
diff --git a/build/targets.sh b/build/targets.sh
index f900f6e68..09e619b62 100644
--- a/build/targets.sh
+++ b/build/targets.sh
@@ -1,4 +1,17 @@
+#########################################################################
+# #
+# Objective Caml #
+# #
+# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt #
+# #
+# Copyright 2007 Institut National de Recherche en Informatique et #
+# en Automatique. All rights reserved. This file is distributed #
+# under the terms of the Q Public License version 1.0. #
+# #
+#########################################################################
+
# $Id$
+
. config/config.sh
. build/otherlibs-targets.sh
. build/camlp4-targets.sh
diff --git a/bytecomp/matching.ml b/bytecomp/matching.ml
index 184626dfa..f7caf464e 100644
--- a/bytecomp/matching.ml
+++ b/bytecomp/matching.ml
@@ -2337,8 +2337,8 @@ and do_compile_matching repr partial ctx arg pmh = match pmh with
ctx pm
| Tpat_variant(lab, _, row) ->
compile_test (compile_match repr partial) partial
- (divide_variant row)
- (combine_variant row arg partial)
+ (divide_variant !row)
+ (combine_variant !row arg partial)
ctx pm
| _ -> assert false
end
diff --git a/bytecomp/translclass.ml b/bytecomp/translclass.ml
index 7ea71185e..d186bdebf 100644
--- a/bytecomp/translclass.ml
+++ b/bytecomp/translclass.ml
@@ -73,10 +73,10 @@ let transl_val tbl create name =
mkappl (oo_prim (if create then "new_variable" else "get_variable"),
[Lvar tbl; transl_label name])
-let transl_vals tbl create vals rem =
+let transl_vals tbl create strict vals rem =
List.fold_right
(fun (name, id) rem ->
- Llet(StrictOpt, id, transl_val tbl create name, rem))
+ Llet(strict, id, transl_val tbl create name, rem))
vals rem
let meths_super tbl meths inh_meths =
@@ -90,7 +90,7 @@ let meths_super tbl meths inh_meths =
inh_meths []
let bind_super tbl (vals, meths) cl_init =
- transl_vals tbl false vals
+ transl_vals tbl false StrictOpt vals
(List.fold_right (fun (nm, id, def) rem -> Llet(StrictOpt, id, def, rem))
meths cl_init)
@@ -205,22 +205,22 @@ let rec build_object_init_0 cl_table params cl copy_env subst_env top ids =
let bind_method tbl lab id cl_init =
- Llet(StrictOpt, id, mkappl (oo_prim "get_method_label",
- [Lvar tbl; transl_label lab]),
+ Llet(Strict, id, mkappl (oo_prim "get_method_label",
+ [Lvar tbl; transl_label lab]),
cl_init)
let bind_methods tbl meths vals cl_init =
let methl = Meths.fold (fun lab id tl -> (lab,id) :: tl) meths [] in
let len = List.length methl and nvals = List.length vals in
if len < 2 && nvals = 0 then Meths.fold (bind_method tbl) meths cl_init else
- if len = 0 && nvals < 2 then transl_vals tbl true vals cl_init else
+ if len = 0 && nvals < 2 then transl_vals tbl true Strict vals cl_init else
let ids = Ident.create "ids" in
let i = ref (len + nvals) in
let getter, names =
if nvals = 0 then "get_method_labels", [] else
"new_methods_variables", [transl_meth_list (List.map fst vals)]
in
- Llet(StrictOpt, ids,
+ Llet(Strict, ids,
mkappl (oo_prim getter,
[Lvar tbl; transl_meth_list (List.map fst methl)] @ names),
List.fold_right
@@ -248,6 +248,8 @@ let rec index a = function
| b :: l ->
if b = a then 0 else 1 + index a l
+let bind_id_as_val (id, _) = ("", id)
+
let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
match cl.cl_desc with
Tclass_ident path ->
@@ -310,16 +312,16 @@ let rec build_class_init cla cstr super inh_init cl_init msubst top cl =
let (inh_init, cl_init) =
build_class_init cla cstr super inh_init cl_init msubst top cl
in
- let vals = List.map (function (id, _) -> (Ident.name id, id)) vals in
- (inh_init, transl_vals cla true vals cl_init)
+ let vals = List.map bind_id_as_val vals in
+ (inh_init, transl_vals cla true StrictOpt vals cl_init)
| Tclass_apply (cl, exprs) ->
build_class_init cla cstr super inh_init cl_init msubst top cl
| Tclass_let (rec_flag, defs, vals, cl) ->
let (inh_init, cl_init) =
build_class_init cla cstr super inh_init cl_init msubst top cl
in
- let vals = List.map (function (id, _) -> (Ident.name id, id)) vals in
- (inh_init, transl_vals cla true vals cl_init)
+ let vals = List.map bind_id_as_val vals in
+ (inh_init, transl_vals cla true StrictOpt vals cl_init)
| Tclass_constraint (cl, vals, meths, concr_meths) ->
let virt_meths =
List.filter (fun lab -> not (Concr.mem lab concr_meths)) meths in
@@ -586,6 +588,9 @@ open M
Si ids=0 (objet immediat), alors on ne conserve que env_init.
*)
+let prerr_ids msg ids =
+ let names = List.map Ident.unique_toplevel_name ids in
+ prerr_endline (String.concat " " (msg :: names))
let transl_class ids cl_id arity pub_meths cl vflag =
(* First check if it is not only a rebind *)
@@ -603,10 +608,6 @@ let transl_class ids cl_id arity pub_meths cl vflag =
let subst env lam i0 new_ids' =
let fv = free_variables lam in
let fv = List.fold_right IdentSet.remove !new_ids' fv in
- (* IdentSet.iter
- (fun id ->
- if not (List.mem id new_ids) then prerr_endline (Ident.name id))
- fv; *)
let fv = IdentSet.filter (fun id -> List.mem id new_ids) fv in
(* need to handle methods specially (PR#3576) *)
let fm = IdentSet.diff (free_methods lam) meth_ids in
diff --git a/bytecomp/translmod.ml b/bytecomp/translmod.ml
index 9125d8e7e..fc7da7d1a 100644
--- a/bytecomp/translmod.ml
+++ b/bytecomp/translmod.ml
@@ -335,7 +335,7 @@ and transl_structure fields cc rootpath = function
| id :: ids ->
Llet(Alias, id, Lprim(Pfield pos, [Lvar mid]),
rebind_idents (pos + 1) (id :: newfields) ids) in
- Llet(Alias, mid, transl_module Tcoerce_none None modl,
+ Llet(Strict, mid, transl_module Tcoerce_none None modl,
rebind_idents 0 fields ids)
(* Update forward declaration in Translcore *)
@@ -539,7 +539,7 @@ let build_ident_map restr idlist =
| _ ->
fatal_error "Translmod.build_ident_map"
-(* Compile an implementation using transl_store_structure
+(* Compile an implementation using transl_store_structure
(for the native-code compiler). *)
let transl_store_gen module_name (str, restr) topl =
@@ -549,8 +549,8 @@ let transl_store_gen module_name (str, restr) topl =
let (map, prims, size) = build_ident_map restr (defined_idents str) in
let f = function
| [ Tstr_eval expr ] when topl ->
- assert (size = 0);
- subst_lambda !transl_store_subst (transl_exp expr)
+ assert (size = 0);
+ subst_lambda !transl_store_subst (transl_exp expr)
| str -> transl_store_structure module_id map prims str in
transl_store_label_init module_id size f str
(*size, transl_label_init (transl_store_structure module_id map prims str)*)
@@ -665,7 +665,7 @@ let transl_toplevel_definition str =
let get_component = function
None -> Lconst const_unit
- | Some id -> Lprim(Pgetglobal id, [])
+ | Some id -> Lprim(Pgetglobal id, [])
let transl_package component_names target_name coercion =
let components =
diff --git a/byterun/compare.c b/byterun/compare.c
index 42b1d9d73..35a7f66ce 100644
--- a/byterun/compare.c
+++ b/byterun/compare.c
@@ -268,14 +268,14 @@ CAMLprim value caml_lessthan(value v1, value v2)
{
intnat res = compare_val(v1, v2, 0);
if (compare_stack != compare_stack_init) compare_free_stack();
- return Val_int(res - 1 < -1);
+ return Val_int(res < 0 && res != UNORDERED);
}
CAMLprim value caml_lessequal(value v1, value v2)
{
intnat res = compare_val(v1, v2, 0);
if (compare_stack != compare_stack_init) compare_free_stack();
- return Val_int(res - 1 <= -1);
+ return Val_int(res <= 0 && res != UNORDERED);
}
CAMLprim value caml_greaterthan(value v1, value v2)
diff --git a/byterun/finalise.c b/byterun/finalise.c
index dce6edd61..44a5876d2 100644
--- a/byterun/finalise.c
+++ b/byterun/finalise.c
@@ -24,6 +24,7 @@
struct final {
value fun;
value val;
+ int offset;
};
static struct final *final_table = NULL;
@@ -67,7 +68,7 @@ void caml_final_update (void)
{
uintnat i, j, k;
uintnat todo_count = 0;
-
+
Assert (young == old);
for (i = 0; i < old; i++){
Assert (Is_block (final_table[i].val));
@@ -84,6 +85,7 @@ void caml_final_update (void)
Assert (Is_in_heap (final_table[i].val));
if (Is_white_val (final_table[i].val)){
if (Tag_val (final_table[i].val) == Forward_tag){
+ Assert (final_table[i].offset == 0);
value fv = Forward_val (final_table[i].val);
if (Is_block (fv) && Is_in_value_area(fv)
&& (Tag_val (fv) == Forward_tag || Tag_val (fv) == Lazy_tag
@@ -136,7 +138,7 @@ void caml_final_do_calls (void)
-- to_do_hd->size;
f = to_do_hd->item[to_do_hd->size];
running_finalisation_function = 1;
- caml_callback (f.fun, f.val);
+ caml_callback (f.fun, f.val + f.offset);
running_finalisation_function = 0;
}
caml_gc_message (0x80, "Done calling finalisation functions.\n", 0);
@@ -159,7 +161,7 @@ void caml_final_do_strong_roots (scanning_action f)
Assert (old == young);
for (i = 0; i < old; i++) Call_action (f, final_table[i].fun);
-
+
for (todo = to_do_hd; todo != NULL; todo = todo->next){
for (i = 0; i < todo->size; i++){
Call_action (f, todo->item[i].fun);
@@ -186,7 +188,7 @@ void caml_final_do_weak_roots (scanning_action f)
void caml_final_do_young_roots (scanning_action f)
{
uintnat i;
-
+
Assert (old <= young);
for (i = old; i < young; i++){
Call_action (f, final_table[i].fun);
@@ -210,7 +212,7 @@ CAMLprim value caml_final_register (value f, value v)
caml_invalid_argument ("Gc.finalise");
}
Assert (old <= young);
-
+
if (young >= size){
if (final_table == NULL){
uintnat new_size = 30;
@@ -227,8 +229,13 @@ CAMLprim value caml_final_register (value f, value v)
}
Assert (young < size);
final_table[young].fun = f;
- if (Tag_val (v) == Infix_tag) v -= Infix_offset_val (v);
- final_table[young].val = v;
+ if (Tag_val (v) == Infix_tag){
+ final_table[young].offset = Infix_offset_val (v);
+ final_table[young].val = v - Infix_offset_val (v);
+ }else{
+ final_table[young].offset = 0;
+ final_table[young].val = v;
+ }
++ young;
return Val_unit;
diff --git a/byterun/gc_ctrl.c b/byterun/gc_ctrl.c
index 1dce5cb08..5f028c0eb 100644
--- a/byterun/gc_ctrl.c
+++ b/byterun/gc_ctrl.c
@@ -78,7 +78,7 @@ static void check_block (char *hp)
mlsize_t i;
value v = Val_hp (hp);
value f;
-
+
check_head (v);
switch (Tag_hp (hp)){
case Abstract_tag: break;
@@ -93,7 +93,7 @@ static void check_block (char *hp)
case Custom_tag:
Assert (!Is_in_heap (Custom_ops_val (v)));
break;
-
+
case Infix_tag:
Assert (0);
break;
@@ -102,7 +102,10 @@ static void check_block (char *hp)
Assert (Tag_hp (hp) < No_scan_tag);
for (i = 0; i < Wosize_hp (hp); i++){
f = Field (v, i);
- if (Is_block (f) && Is_in_heap (f)) check_head (f);
+ if (Is_block (f) && Is_in_heap (f)){
+ check_head (f);
+ Assert (Color_val (f) != Caml_blue);
+ }
}
}
}
diff --git a/byterun/intern.c b/byterun/intern.c
index 5f99b5b06..b7acfd4a0 100644
--- a/byterun/intern.c
+++ b/byterun/intern.c
@@ -76,7 +76,7 @@ static value intern_block;
(Sign_extend(intern_src[-2]) << 8) + intern_src[-1])
#define read32u() \
(intern_src += 4, \
- (intern_src[-4] << 24) + (intern_src[-3] << 16) + \
+ ((uintnat)(intern_src[-4]) << 24) + (intern_src[-3] << 16) + \
(intern_src[-2] << 8) + intern_src[-1])
#define read32s() \
(intern_src += 4, \
diff --git a/byterun/ints.c b/byterun/ints.c
index 23ee46329..ed18e6f44 100644
--- a/byterun/ints.c
+++ b/byterun/ints.c
@@ -551,15 +551,21 @@ CAMLprim value caml_int64_of_string(value s)
CAMLprim value caml_int64_bits_of_float(value vd)
{
- union { double d; int64 i; } u;
+ union { double d; int64 i; int32 h[2]; } u;
u.d = Double_val(vd);
+#if defined(__arm__) && !defined(__ARM_EABI__)
+ { int32 t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; }
+#endif
return caml_copy_int64(u.i);
}
CAMLprim value caml_int64_float_of_bits(value vi)
{
- union { double d; int64 i; } u;
+ union { double d; int64 i; int32 h[2]; } u;
u.i = Int64_val(vi);
+#if defined(__arm__) && !defined(__ARM_EABI__)
+ { int32 t = u.h[0]; u.h[0] = u.h[1]; u.h[1] = t; }
+#endif
return caml_copy_double(u.d);
}
diff --git a/byterun/io.h b/byterun/io.h
index a35124ac9..127c4c1c5 100644
--- a/byterun/io.h
+++ b/byterun/io.h
@@ -52,7 +52,7 @@ struct channel {
};
enum {
- CHANNEL_FLAG_FROM_SOCKET = 1, /* For Windows */
+ CHANNEL_FLAG_FROM_SOCKET = 1 /* For Windows */
};
/* For an output channel:
diff --git a/byterun/major_gc.c b/byterun/major_gc.c
index 3c903740a..d12982b1a 100644
--- a/byterun/major_gc.c
+++ b/byterun/major_gc.c
@@ -190,23 +190,27 @@ static void mark_slice (intnat work)
chunk = caml_heap_start;
markhp = chunk;
limit = chunk + Chunk_size (chunk);
- }else if (caml_gc_subphase == Subphase_main){
- /* The main marking phase is over. Start removing weak pointers to
- dead values. */
- caml_gc_subphase = Subphase_weak1;
- weak_prev = &caml_weak_list_head;
- }else if (caml_gc_subphase == Subphase_weak1){
- value cur, curfield;
- mlsize_t sz, i;
- header_t hd;
-
- cur = *weak_prev;
- if (cur != (value) NULL){
- hd = Hd_val (cur);
+ }else{
+ switch (caml_gc_subphase){
+ case Subphase_main: {
+ /* The main marking phase is over. Start removing weak pointers to
+ dead values. */
+ caml_gc_subphase = Subphase_weak1;
+ weak_prev = &caml_weak_list_head;
+ }
+ break;
+ case Subphase_weak1: {
+ value cur, curfield;
+ mlsize_t sz, i;
+ header_t hd;
+
+ cur = *weak_prev;
+ if (cur != (value) NULL){
+ hd = Hd_val (cur);
sz = Wosize_hd (hd);
for (i = 1; i < sz; i++){
curfield = Field (cur, i);
- weak_again:
+ weak_again:
if (curfield != caml_weak_none
&& Is_block (curfield) && Is_in_heap (curfield)){
if (Tag_val (curfield) == Forward_tag){
@@ -226,46 +230,53 @@ static void mark_slice (intnat work)
}
}
}
- weak_prev = &Field (cur, 0);
- work -= Whsize_hd (hd);
- }else{
- /* Subphase_weak1 is done. Start removing dead weak arrays. */
- caml_gc_subphase = Subphase_weak2;
- weak_prev = &caml_weak_list_head;
+ weak_prev = &Field (cur, 0);
+ work -= Whsize_hd (hd);
+ }else{
+ /* Subphase_weak1 is done. Start removing dead weak arrays. */
+ caml_gc_subphase = Subphase_weak2;
+ weak_prev = &caml_weak_list_head;
+ }
}
- }else if (caml_gc_subphase == Subphase_weak2){
- value cur;
- header_t hd;
-
- cur = *weak_prev;
- if (cur != (value) NULL){
- hd = Hd_val (cur);
- if (Color_hd (hd) == Caml_white){
- /* The whole array is dead, remove it from the list. */
- *weak_prev = Field (cur, 0);
+ break;
+ case Subphase_weak2: {
+ value cur;
+ header_t hd;
+
+ cur = *weak_prev;
+ if (cur != (value) NULL){
+ hd = Hd_val (cur);
+ if (Color_hd (hd) == Caml_white){
+ /* The whole array is dead, remove it from the list. */
+ *weak_prev = Field (cur, 0);
+ }else{
+ weak_prev = &Field (cur, 0);
+ }
+ work -= 1;
}else{
- weak_prev = &Field (cur, 0);
+ /* Subphase_weak2 is done. Handle finalised values. */
+ gray_vals_cur = gray_vals_ptr;
+ caml_final_update ();
+ gray_vals_ptr = gray_vals_cur;
+ caml_gc_subphase = Subphase_final;
}
- work -= 1;
- }else{
- /* Subphase_weak2 is done. Handle finalised values. */
+ }
+ break;
+ case Subphase_final: {
+ /* Initialise the sweep phase. */
gray_vals_cur = gray_vals_ptr;
- caml_final_update ();
- gray_vals_ptr = gray_vals_cur;
- caml_gc_subphase = Subphase_final;
+ caml_gc_sweep_hp = caml_heap_start;
+ caml_fl_init_merge ();
+ caml_gc_phase = Phase_sweep;
+ chunk = caml_heap_start;
+ caml_gc_sweep_hp = chunk;
+ limit = chunk + Chunk_size (chunk);
+ work = 0;
+ caml_fl_size_at_phase_change = caml_fl_cur_size;
+ }
+ break;
+ default: Assert (0);
}
- }else{
- Assert (caml_gc_subphase == Subphase_final);
- /* Initialise the sweep phase. */
- gray_vals_cur = gray_vals_ptr;
- caml_gc_sweep_hp = caml_heap_start;
- caml_fl_init_merge ();
- caml_gc_phase = Phase_sweep;
- chunk = caml_heap_start;
- caml_gc_sweep_hp = chunk;
- limit = chunk + Chunk_size (chunk);
- work = 0;
- caml_fl_size_at_phase_change = caml_fl_cur_size;
}
}
gray_vals_cur = gray_vals_ptr;
diff --git a/byterun/minor_gc.c b/byterun/minor_gc.c
index 16526f85e..4288f9e96 100644
--- a/byterun/minor_gc.c
+++ b/byterun/minor_gc.c
@@ -39,6 +39,10 @@ CAMLexport struct caml_ref_table
int caml_in_minor_collection = 0;
+#ifdef DEBUG
+static unsigned long minor_gc_counter = 0;
+#endif
+
void caml_alloc_table (struct caml_ref_table *tbl, asize_t sz, asize_t rsv)
{
value **new_table;
@@ -248,6 +252,7 @@ void caml_empty_minor_heap (void)
for (p = (value *) caml_young_start; p < (value *) caml_young_end; ++p){
*p = Debug_free_minor;
}
+ ++ minor_gc_counter;
}
#endif
}
diff --git a/camlp4/Camlp4/Printers/OCaml.ml b/camlp4/Camlp4/Printers/OCaml.ml
index 5142b3815..a637dffef 100644
--- a/camlp4/Camlp4/Printers/OCaml.ml
+++ b/camlp4/Camlp4/Printers/OCaml.ml
@@ -321,7 +321,7 @@ module Make (Syntax : Sig.Camlp4Syntax) = struct
| [e] -> pp f "[ %a ]" o#under_semi#expr e
| el -> pp f "@[<2>[ %a@] ]" (list o#under_semi#expr ";@ ") el ];
- method expr_list_cons simple f e =
+ method expr_list_cons simple f e =
let (el, c) = o#mk_expr_list e in
match c with
[ None -> o#expr_list f el
@@ -496,7 +496,7 @@ module Make (Syntax : Sig.Camlp4Syntax) = struct
| <:expr< ( $tup:e$ ) >> ->
pp f "@[<1>(%a)@]" o#expr e
| <:expr< [| $e$ |] >> ->
- pp f "@[<0>@[<2>[|@ %a@]@ |]@]" o#under_semi#expr e
+ pp f "@[<0>@[<2>[|@ %a@]@ |]@]" o#under_semi#expr e
| <:expr< ($e$ :> $t$) >> ->
pp f "@[<2>(%a :>@ %a)@]" o#expr e o#ctyp t
| <:expr< ($e$ : $t1$ :> $t2$) >> ->
@@ -903,7 +903,7 @@ module Make (Syntax : Sig.Camlp4Syntax) = struct
| <:class_expr< $ce1$ and $ce2$ >> ->
do { o#class_expr f ce1; pp f andsep; o#class_expr f ce2 }
| <:class_expr< $ce1$ = fun $p$ -> $ce2$ >> when is_irrefut_patt p ->
- pp f "@[<2>%a@ %a" o#class_expr ce1
+ pp f "@[<2>%a@ %a" o#class_expr ce1
o#patt_class_expr_fun_args (p, ce2)
| <:class_expr< $ce1$ = $ce2$ >> ->
pp f "@[<2>%a =@]@ %a" o#class_expr ce1 o#class_expr ce2
diff --git a/camlp4/Camlp4/Printers/OCamlr.ml b/camlp4/Camlp4/Printers/OCamlr.ml
index 15a2cfd42..64086607d 100644
--- a/camlp4/Camlp4/Printers/OCamlr.ml
+++ b/camlp4/Camlp4/Printers/OCamlr.ml
@@ -147,7 +147,7 @@ module Make (Syntax : Sig.Camlp4Syntax) = struct
| Some x -> pp f "@[<2>[ %a ::@ %a ]@]" (list o#patt ";@ ") pl o#patt x ]
| p -> super#patt4 f p ];
- method expr_list_cons _ f e =
+ method expr_list_cons _ f e =
let (el, c) = o#mk_expr_list e in
match c with
[ None -> o#expr_list f el
diff --git a/camlp4/Camlp4/Sig.ml b/camlp4/Camlp4/Sig.ml
index e96c3e714..253dc4185 100644
--- a/camlp4/Camlp4/Sig.ml
+++ b/camlp4/Camlp4/Sig.ml
@@ -18,6 +18,8 @@
* - Nicolas Pouillard: refactoring
*)
+(* $Id$ *)
+
(** Camlp4 signature repository *)
(** {6 Basic signatures} *)
@@ -42,7 +44,7 @@ module type Id = sig
(** The name of the extension, typically the module name. *)
value name : string;
- (** The version of the extension, typically $Id$ with a versionning system. *)
+ (** The version of the extension, typically $ Id$ with a versionning system. *)
value version : string;
end;
diff --git a/camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.ml b/camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.ml
index 25c30d570..45b65fb64 100644
--- a/camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.ml
+++ b/camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.ml
@@ -199,7 +199,7 @@ module Make (Ast : Sig.Camlp4Ast) = struct
value rec ty_var_list_of_ctyp =
fun
[ <:ctyp< $t1$ $t2$ >> -> ty_var_list_of_ctyp t1 @ ty_var_list_of_ctyp t2
- | <:ctyp< '$s$ >> -> [s]
+ | <:ctyp< '$s$ >> -> [s]
| _ -> assert False ];
value rec ctyp =
@@ -495,7 +495,7 @@ module Make (Ast : Sig.Camlp4Ast) = struct
mkpat loc (Ppat_constant (Const_string (string_of_string_token loc s)))
| <:patt@loc< ($p1$, $p2$) >> ->
mkpat loc (Ppat_tuple
- (List.map patt (list_of_patt p1 (list_of_patt p2 []))))
+ (List.map patt (list_of_patt p1 (list_of_patt p2 []))))
| <:patt@loc< ($tup:_$) >> -> error loc "singleton tuple pattern"
| PaTyc loc p t -> mkpat loc (Ppat_constraint (patt p) (ctyp t))
| PaTyp loc i -> mkpat loc (Ppat_type (long_type_ident i))
@@ -678,7 +678,7 @@ module Make (Ast : Sig.Camlp4Ast) = struct
| ExLmd loc i me e -> mkexp loc (Pexp_letmodule i (module_expr me) (expr e))
| ExMat loc e a -> mkexp loc (Pexp_match (expr e) (match_case a []))
| ExNew loc id -> mkexp loc (Pexp_new (long_type_ident id))
- | ExObj loc po cfl ->
+ | ExObj loc po cfl ->
let p =
match po with
[ <:patt<>> -> <:patt@loc< _ >>
@@ -716,7 +716,7 @@ module Make (Ast : Sig.Camlp4Ast) = struct
mkexp loc (Pexp_constant (Const_string (string_of_string_token loc s)))
| ExTry loc e a -> mkexp loc (Pexp_try (expr e) (match_case a []))
| <:expr@loc< ($e1$, $e2$) >> ->
- mkexp loc (Pexp_tuple (List.map expr (list_of_expr e1 (list_of_expr e2 []))))
+ mkexp loc (Pexp_tuple (List.map expr (list_of_expr e1 (list_of_expr e2 []))))
| <:expr@loc< ($tup:_$) >> -> error loc "singleton tuple"
| ExTyc loc e t -> mkexp loc (Pexp_constraint (expr e) (Some (ctyp t)) None)
| <:expr@loc< () >> ->
@@ -920,7 +920,7 @@ module Make (Ast : Sig.Camlp4Ast) = struct
error loc "invalid virtual class inside a class type"
| CtAnt _ _ | CtEq _ _ _ | CtCol _ _ _ | CtAnd _ _ _ | CtNil _ ->
assert False ]
-
+
and class_info_class_expr ci =
match ci with
[ CeEq _ (CeCon loc vir (IdLid _ name) params) ce ->
diff --git a/camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.mli b/camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.mli
index b94bad940..922789153 100644
--- a/camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.mli
+++ b/camlp4/Camlp4/Struct/Camlp4Ast2OCamlAst.mli
@@ -18,7 +18,6 @@
* - Nicolas Pouillard: refactoring
*)
-
(* $Id$ *)
module Make (Camlp4Ast : Sig.Camlp4Ast) : sig
diff --git a/camlp4/Camlp4/Struct/Lexer.mll b/camlp4/Camlp4/Struct/Lexer.mll
index a433b606c..6344993a0 100644
--- a/camlp4/Camlp4/Struct/Lexer.mll
+++ b/camlp4/Camlp4/Struct/Lexer.mll
@@ -17,7 +17,6 @@
* - Nicolas Pouillard: refactoring
*)
-
(* $Id$ *)
(* The lexer definition *)
diff --git a/camlp4/Camlp4Bin.ml b/camlp4/Camlp4Bin.ml
index 4961c5e07..0fea725a2 100644
--- a/camlp4/Camlp4Bin.ml
+++ b/camlp4/Camlp4Bin.ml
@@ -49,7 +49,7 @@ value add_to_loaded_modules name =
loaded_modules.val := SSet.add name loaded_modules.val;
value (objext,libext) =
- if DynLoader.is_native then (".cmxs",".cmxs")
+ if DynLoader.is_native then (".cmxs",".cmxs")
else (".cmo",".cma");
value rewrite_and_load n x =
@@ -219,7 +219,7 @@ value (task, do_task) =
value input_file x =
let dyn_loader = dyn_loader.val () in
do {
- rcall_callback.val ();
+ rcall_callback.val ();
match x with
[ Intf file_name -> task (process_intf dyn_loader) file_name
| Impl file_name -> task (process_impl dyn_loader) file_name
diff --git a/camlp4/Camlp4Top/Rprint.ml b/camlp4/Camlp4Top/Rprint.ml
index 3b27a5943..f6d15b51a 100644
--- a/camlp4/Camlp4Top/Rprint.ml
+++ b/camlp4/Camlp4Top/Rprint.ml
@@ -18,7 +18,6 @@
* - Nicolas Pouillard: refactoring
*)
-
(* $Id$ *)
(* There is a few Obj.magic due to the fact that we no longer have compiler
diff --git a/config/Makefile.msvc b/config/Makefile.msvc
index e888c3a4b..9a4732563 100644
--- a/config/Makefile.msvc
+++ b/config/Makefile.msvc
@@ -80,7 +80,7 @@ BYTECC=cl /nologo -D_CRT_SECURE_NO_DEPRECATE
BYTECCCOMPOPTS=/Ox /MD
### Additional link-time options for $(BYTECC). (For static linking.)
-BYTECCLINKOPTS=/MD
+BYTECCLINKOPTS=/MD /F16777216
### Additional compile-time options for $(BYTECC). (For building a DLL.)
DLLCCCOMPOPTS=/Ox /MD
@@ -131,7 +131,7 @@ NATIVECC=cl /nologo -D_CRT_SECURE_NO_DEPRECATE
NATIVECCCOMPOPTS=/Ox /MD
### Additional link-time options for $(NATIVECC)
-NATIVECCLINKOPTS=/MD
+NATIVECCLINKOPTS=/MD /F16777216
### Build partially-linked object file
PACKLD=link /lib /nologo /out:# there must be no space after this '/out:'
diff --git a/config/Makefile.msvc64 b/config/Makefile.msvc64
index 2a06de920..cef571117 100644
--- a/config/Makefile.msvc64
+++ b/config/Makefile.msvc64
@@ -83,7 +83,7 @@ BYTECCCOMPOPTS=/Ox /MD
BYTECCDBGCOMPOPTS=-DDEBUG /Zi /W3 /Wp64
### Additional link-time options for $(BYTECC). (For static linking.)
-BYTECCLINKOPTS=/MD
+BYTECCLINKOPTS=/MD /F33554432
### Additional compile-time options for $(BYTECC). (For building a DLL.)
DLLCCCOMPOPTS=/Ox /MD
@@ -135,7 +135,7 @@ NATIVECC=cl /nologo
NATIVECCCOMPOPTS=/Ox /MD
### Additional link-time options for $(NATIVECC)
-NATIVECCLINKOPTS=/MD
+NATIVECCLINKOPTS=/MD /F33554432
### Build partially-linked object file
PACKLD=link /lib /nologo /machine:AMD64 /out:# there must be no space after this '/out:'
diff --git a/config/auto-aux/stackov.c b/config/auto-aux/stackov.c
index a1aa0b7ec..7f06e9711 100644
--- a/config/auto-aux/stackov.c
+++ b/config/auto-aux/stackov.c
@@ -43,7 +43,7 @@ static void segv_handler(int signo, siginfo_t * info, void * context)
int main(int argc, char ** argv)
{
- struct sigaltstack stk;
+ stack_t stk;
struct sigaction act;
stk.ss_sp = sig_alt_stack;
diff --git a/configure b/configure
index 307f387e5..6a1a9996c 100755
--- a/configure
+++ b/configure
@@ -568,7 +568,7 @@ if test $withsharedlibs = "yes"; then
dyld=ld
if test -f /usr/bin/ld_classic; then
# The new linker in Mac OS X 10.5 does not support read_only_relocs
- dyld=/usr/bin/ld_classic
+ # dyld=/usr/bin/ld_classic XXX FIXME incompatible with X11 libs
fi
mksharedlib="$dyld -bundle -flat_namespace -undefined suppress -read_only_relocs suppress"
bytecccompopts="$dl_defs $bytecccompopts"
@@ -629,7 +629,7 @@ case "$host" in
hppa2.0*-*-hpux*) arch=hppa; system=hpux;;
hppa*-*-linux*) arch=hppa; system=linux;;
hppa*-*-gnu*) arch=hppa; system=gnu;;
- powerpc-*-linux*) arch=power; model=ppc; system=elf;;
+ powerpc*-*-linux*) arch=power; model=ppc; system=elf;;
powerpc-*-netbsd*) arch=power; model=ppc; system=elf;;
powerpc-*-rhapsody*) arch=power; model=ppc; system=rhapsody;;
powerpc-*-darwin*) arch=power; system=rhapsody
@@ -646,6 +646,17 @@ case "$host" in
x86_64-*-openbsd*) arch=amd64; system=openbsd;;
esac
+# Some platforms exist both in 32-bit and 64-bit variants, not distinguished
+# by $host. Turn off native code compilation on platforms where 64-bit mode
+# is not supported. (PR#4441)
+
+if $arch64; then
+ case "$arch,$model" in
+ sparc,default|mips,default|hppa,default|power,ppc)
+ arch=none; model=default; system=unknown;;
+ esac
+fi
+
if test -z "$ccoption"; then
case "$arch,$system,$cc" in
alpha,digital,gcc*) nativecc=cc;;
@@ -1254,6 +1265,7 @@ for dir in \
/usr/x386/lib \
/usr/XFree86/lib/X11 \
\
+ /usr/lib64 \
/usr/lib \
/usr/local/lib \
/usr/unsupported/lib \
diff --git a/debugger/main.ml b/debugger/main.ml
index d74beaca8..4920d0d79 100644
--- a/debugger/main.ml
+++ b/debugger/main.ml
@@ -165,6 +165,7 @@ let main () =
current_prompt := debugger_prompt;
printf "\tObjective Caml Debugger version %s@.@." Config.version;
Config.load_path := !default_load_path;
+ Clflags.recursive_types := true; (* Allow recursive types. *)
toplevel_loop (); (* Toplevel. *)
kill_program ();
exit 0
diff --git a/emacs/README b/emacs/README
index f6bf63e84..7ddb362b4 100644
--- a/emacs/README
+++ b/emacs/README
@@ -63,6 +63,14 @@ For other bindings, see C-h b.
Changes log:
-----------
+Version 3.10.1:
+---------------
+* use caml-font.el from Olivier Andrieu
+ old version is left as caml-font-old.el for compatibility
+
+Version 3.07:
+-------------
+* support for showing type information <Damien Doligez>
Version 3.05:
-------------
@@ -195,4 +203,4 @@ in other cases may confuse the phrase selection function.
Comments and bug reports to
- Jacques Garrigue <garrigue@kurims.kyoto-u.ac.jp>
+ Jacques Garrigue <garrigue@math.nagoya-u.ac.jp>
diff --git a/emacs/caml-font-old.el b/emacs/caml-font-old.el
new file mode 100644
index 000000000..fe5721376
--- /dev/null
+++ b/emacs/caml-font-old.el
@@ -0,0 +1,141 @@
+;(***********************************************************************)
+;(* *)
+;(* Objective Caml *)
+;(* *)
+;(* Jacques Garrigue and Ian T Zimmerman *)
+;(* *)
+;(* Copyright 1997 Institut National de Recherche en Informatique et *)
+;(* en Automatique. All rights reserved. This file is distributed *)
+;(* under the terms of the GNU General Public License. *)
+;(* *)
+;(***********************************************************************)
+
+;(* $Id$ *)
+
+;; useful colors
+
+(cond
+ ((x-display-color-p)
+ (require 'font-lock)
+ (cond
+ ((not (boundp 'font-lock-type-face))
+ ; make the necessary faces
+ (make-face 'Firebrick)
+ (set-face-foreground 'Firebrick "Firebrick")
+ (make-face 'RosyBrown)
+ (set-face-foreground 'RosyBrown "RosyBrown")
+ (make-face 'Purple)
+ (set-face-foreground 'Purple "Purple")
+ (make-face 'MidnightBlue)
+ (set-face-foreground 'MidnightBlue "MidnightBlue")
+ (make-face 'DarkGoldenRod)
+ (set-face-foreground 'DarkGoldenRod "DarkGoldenRod")
+ (make-face 'DarkOliveGreen)
+ (set-face-foreground 'DarkOliveGreen "DarkOliveGreen4")
+ (make-face 'CadetBlue)
+ (set-face-foreground 'CadetBlue "CadetBlue")
+ ; assign them as standard faces
+ (setq font-lock-comment-face 'Firebrick)
+ (setq font-lock-string-face 'RosyBrown)
+ (setq font-lock-keyword-face 'Purple)
+ (setq font-lock-function-name-face 'MidnightBlue)
+ (setq font-lock-variable-name-face 'DarkGoldenRod)
+ (setq font-lock-type-face 'DarkOliveGreen)
+ (setq font-lock-reference-face 'CadetBlue)))
+ ; extra faces for documention
+ (make-face 'Stop)
+ (set-face-foreground 'Stop "White")
+ (set-face-background 'Stop "Red")
+ (make-face 'Doc)
+ (set-face-foreground 'Doc "Red")
+ (setq font-lock-stop-face 'Stop)
+ (setq font-lock-doccomment-face 'Doc)
+))
+
+; The same definition is in caml.el:
+; we don't know in which order they will be loaded.
+(defvar caml-quote-char "'"
+ "*Quote for character constants. \"'\" for Objective Caml, \"`\" for Caml-Light.")
+
+(defconst caml-font-lock-keywords
+ (list
+;stop special comments
+ '("\\(^\\|[^\"]\\)\\((\\*\\*/\\*\\*)\\)"
+ 2 font-lock-stop-face)
+;doccomments
+ '("\\(^\\|[^\"]\\)\\((\\*\\*[^*]*\\([^)*][^*]*\\*+\\)*)\\)"
+ 2 font-lock-doccomment-face)
+;comments
+ '("\\(^\\|[^\"]\\)\\((\\*[^*]*\\*+\\([^)*][^*]*\\*+\\)*)\\)"
+ 2 font-lock-comment-face)
+;character literals
+ (cons (concat caml-quote-char "\\(\\\\\\([ntbr" caml-quote-char "\\]\\|"
+ "[0-9][0-9][0-9]\\)\\|.\\)" caml-quote-char
+ "\\|\"[^\"\\]*\\(\\\\\\(.\\|\n\\)[^\"\\]*\\)*\"")
+ 'font-lock-string-face)
+;modules and constructors
+ '("`?\\<[A-Z][A-Za-z0-9_']*\\>" . font-lock-function-name-face)
+;definition
+ (cons (concat
+ "\\<\\(a\\(nd\\|s\\)\\|c\\(onstraint\\|lass\\)"
+ "\\|ex\\(ception\\|ternal\\)\\|fun\\(ct\\(ion\\|or\\)\\)?"
+ "\\|in\\(herit\\|itializer\\)?\\|let"
+ "\\|m\\(ethod\\|utable\\|odule\\)"
+ "\\|of\\|p\\(arser\\|rivate\\)\\|rec\\|type"
+ "\\|v\\(al\\|irtual\\)\\)\\>")
+ 'font-lock-type-face)
+;blocking
+ '("\\<\\(begin\\|end\\|object\\|s\\(ig\\|truct\\)\\)\\>"
+ . font-lock-keyword-face)
+;control
+ (cons (concat
+ "\\<\\(do\\(ne\\|wnto\\)?\\|else\\|for\\|i\\(f\\|gnore\\)"
+ "\\|lazy\\|match\\|new\\|or\\|t\\(hen\\|o\\|ry\\)"
+ "\\|w\\(h\\(en\\|ile\\)\\|ith\\)\\)\\>"
+ "\\|\|\\|->\\|&\\|#")
+ 'font-lock-reference-face)
+ '("\\<raise\\>" . font-lock-comment-face)
+;labels (and open)
+ '("\\(\\([~?]\\|\\<\\)[a-z][a-zA-Z0-9_']*:\\)[^:=]" 1
+ font-lock-variable-name-face)
+ '("\\<\\(assert\\|open\\|include\\)\\>\\|[~?][ (]*[a-z][a-zA-Z0-9_']*"
+ . font-lock-variable-name-face)))
+
+(defconst inferior-caml-font-lock-keywords
+ (append
+ (list
+;inferior
+ '("^[#-]" . font-lock-comment-face))
+ caml-font-lock-keywords))
+
+;; font-lock commands are similar for caml-mode and inferior-caml-mode
+(defun caml-mode-font-hook ()
+ (cond
+ ((fboundp 'global-font-lock-mode)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults
+ '(caml-font-lock-keywords nil nil ((?' . "w") (?_ . "w")))))
+ (t
+ (setq font-lock-keywords caml-font-lock-keywords)))
+ (make-local-variable 'font-lock-keywords-only)
+ (setq font-lock-keywords-only t)
+ (font-lock-mode 1))
+
+(add-hook 'caml-mode-hook 'caml-mode-font-hook)
+
+(defun inferior-caml-mode-font-hook ()
+ (cond
+ ((fboundp 'global-font-lock-mode)
+ (make-local-variable 'font-lock-defaults)
+ (setq font-lock-defaults
+ '(inferior-caml-font-lock-keywords
+ nil nil ((?' . "w") (?_ . "w")))))
+ (t
+ (setq font-lock-keywords inferior-caml-font-lock-keywords)))
+ (make-local-variable 'font-lock-keywords-only)
+ (setq font-lock-keywords-only t)
+ (font-lock-mode 1))
+
+(add-hook 'inferior-caml-mode-hooks 'inferior-caml-mode-font-hook)
+
+(provide 'caml-font)
diff --git a/emacs/caml-font.el b/emacs/caml-font.el
index a04d5c94e..2914fdfda 100644
--- a/emacs/caml-font.el
+++ b/emacs/caml-font.el
@@ -1,140 +1,113 @@
-;(***********************************************************************)
-;(* *)
-;(* Objective Caml *)
-;(* *)
-;(* Jacques Garrigue and Ian T Zimmerman *)
-;(* *)
-;(* Copyright 1997 Institut National de Recherche en Informatique et *)
-;(* en Automatique. All rights reserved. This file is distributed *)
-;(* under the terms of the GNU General Public License. *)
-;(* *)
-;(***********************************************************************)
+;; caml-font: font-lock support for OCaml files
+;;
+;; rewrite and clean-up.
+;; Changes:
+;; - fontify strings and comments using syntactic font lock
+;; - define a `font-lock-syntactic-face-function' to fontify ocamldoc comments
+;; - fontify infix operators like mod, land, lsl, etc.
+;; - fontify line number directives
+;; - fontify "failwith" and "invalid_arg" like "raise"
+;; - fontify '\x..' character constants
+;; - use the regexp-opt function to build regexps (more readable)
+;; - use backquote and comma in sexp (more readable)
+;; - drop the `caml-quote-char' variable (I don't use caml-light :))
+;; - stop doing weird things with faces
-;(* $Id$ *)
-;; useful colors
+(require 'font-lock)
-(cond
- ((x-display-color-p)
- (require 'font-lock)
- (cond
- ((not (boundp 'font-lock-type-face))
- ; make the necessary faces
- (make-face 'Firebrick)
- (set-face-foreground 'Firebrick "Firebrick")
- (make-face 'RosyBrown)
- (set-face-foreground 'RosyBrown "RosyBrown")
- (make-face 'Purple)
- (set-face-foreground 'Purple "Purple")
- (make-face 'MidnightBlue)
- (set-face-foreground 'MidnightBlue "MidnightBlue")
- (make-face 'DarkGoldenRod)
- (set-face-foreground 'DarkGoldenRod "DarkGoldenRod")
- (make-face 'DarkOliveGreen)
- (set-face-foreground 'DarkOliveGreen "DarkOliveGreen4")
- (make-face 'CadetBlue)
- (set-face-foreground 'CadetBlue "CadetBlue")
- ; assign them as standard faces
- (setq font-lock-comment-face 'Firebrick)
- (setq font-lock-string-face 'RosyBrown)
- (setq font-lock-keyword-face 'Purple)
- (setq font-lock-function-name-face 'MidnightBlue)
- (setq font-lock-variable-name-face 'DarkGoldenRod)
- (setq font-lock-type-face 'DarkOliveGreen)
- (setq font-lock-reference-face 'CadetBlue)))
- ; extra faces for documention
- (make-face 'Stop)
- (set-face-foreground 'Stop "White")
- (set-face-background 'Stop "Red")
- (make-face 'Doc)
- (set-face-foreground 'Doc "Red")
- (setq font-lock-stop-face 'Stop)
- (setq font-lock-doccomment-face 'Doc)
-))
+(defvar caml-font-stop-face
+ (progn
+ (make-face 'caml-font-stop-face)
+ (set-face-foreground 'caml-font-stop-face "White")
+ (set-face-background 'caml-font-stop-face "Red")
+ 'caml-font-stop-face))
-; The same definition is in caml.el:
-; we don't know in which order they will be loaded.
-(defvar caml-quote-char "'"
- "*Quote for character constants. \"'\" for Objective Caml, \"`\" for Caml-Light.")
+(defvar caml-font-doccomment-face
+ (progn
+ (make-face 'caml-font-doccomment-face)
+ (set-face-foreground 'caml-font-doccomment-face "Red")
+ 'caml-font-doccomment-face))
+
+(unless (facep 'font-lock-preprocessor-face)
+ (defvar font-lock-preprocessor-face
+ (copy-face 'font-lock-builtin-face
+ 'font-lock-preprocessor-face)))
(defconst caml-font-lock-keywords
- (list
-;stop special comments
- '("\\(^\\|[^\"]\\)\\((\\*\\*/\\*\\*)\\)"
- 2 font-lock-stop-face)
-;doccomments
- '("\\(^\\|[^\"]\\)\\((\\*\\*[^*]*\\([^)*][^*]*\\*+\\)*)\\)"
- 2 font-lock-doccomment-face)
-;comments
- '("\\(^\\|[^\"]\\)\\((\\*[^*]*\\*+\\([^)*][^*]*\\*+\\)*)\\)"
- 2 font-lock-comment-face)
+ `(
;character literals
- (cons (concat caml-quote-char "\\(\\\\\\([ntbr" caml-quote-char "\\]\\|"
- "[0-9][0-9][0-9]\\)\\|.\\)" caml-quote-char
- "\\|\"[^\"\\]*\\(\\\\\\(.\\|\n\\)[^\"\\]*\\)*\"")
- 'font-lock-string-face)
+ ("'\\(.\\|\\\\\\([ntbr\"'\\\\]\\|[0-9]\\{3\\}\\|x[0-9A-Fa-f]\\{2\\}\\)\\)'"
+ . font-lock-string-face)
;modules and constructors
- '("`?\\<[A-Z][A-Za-z0-9_']*\\>" . font-lock-function-name-face)
+ ("`?\\<[A-Z][A-Za-z0-9_']*\\>" . font-lock-function-name-face)
;definition
- (cons (concat
- "\\<\\(a\\(nd\\|s\\)\\|c\\(onstraint\\|lass\\)"
- "\\|ex\\(ception\\|ternal\\)\\|fun\\(ct\\(ion\\|or\\)\\)?"
- "\\|in\\(herit\\|itializer\\)?\\|let"
- "\\|m\\(ethod\\|utable\\|odule\\)"
- "\\|of\\|p\\(arser\\|rivate\\)\\|rec\\|type"
- "\\|v\\(al\\|irtual\\)\\)\\>")
- 'font-lock-type-face)
+ (,(regexp-opt '("and" "as" "constraint" "class"
+ "exception" "external" "fun" "function" "functor"
+ "in" "inherit" "initializer" "let"
+ "method" "mutable" "module" "of" "private" "rec"
+ "type" "val" "virtual")
+ 'words)
+ . font-lock-type-face)
;blocking
- '("\\<\\(begin\\|end\\|object\\|s\\(ig\\|truct\\)\\)\\>"
- . font-lock-keyword-face)
+ (,(regexp-opt '("begin" "end" "object" "sig" "struct") 'words)
+ . font-lock-keyword-face)
+;linenums
+ ("# *[0-9]+" . font-lock-preprocessor-face)
+;infix operators
+ (,(regexp-opt '("asr" "land" "lor" "lsl" "lsr" "lxor" "mod") 'words)
+ . font-lock-builtin-face)
;control
- (cons (concat
- "\\<\\(do\\(ne\\|wnto\\)?\\|else\\|for\\|i\\(f\\|gnore\\)"
- "\\|lazy\\|match\\|new\\|or\\|t\\(hen\\|o\\|ry\\)"
- "\\|w\\(h\\(en\\|ile\\)\\|ith\\)\\)\\>"
- "\\|\|\\|->\\|&\\|#")
- 'font-lock-reference-face)
- '("\\<raise\\>" . font-lock-comment-face)
+ (,(concat "[|#&]\\|->\\|"
+ (regexp-opt '("do" "done" "dowto" "else" "for" "if" "ignore"
+ "lazy" "match" "new" "or" "then" "to" "try"
+ "when" "while" "with")
+ 'words))
+ . font-lock-constant-face)
+ ("\\<raise\\|failwith\\|invalid_arg\\>"
+ . font-lock-comment-face)
;labels (and open)
- '("\\(\\([~?]\\|\\<\\)[a-z][a-zA-Z0-9_']*:\\)[^:=]" 1
- font-lock-variable-name-face)
- '("\\<\\(assert\\|open\\|include\\)\\>\\|[~?][ (]*[a-z][a-zA-Z0-9_']*"
- . font-lock-variable-name-face)))
+ ("\\(\\([~?]\\|\\<\\)[a-z][a-zA-Z0-9_']*:\\)[^:=]"
+ 1 font-lock-variable-name-face)
+ ("\\<\\(assert\\|open\\|include\\)\\>\\|[~?][ (]*[a-z][a-zA-Z0-9_']*"
+ . font-lock-variable-name-face)))
-(defconst inferior-caml-font-lock-keywords
- (append
- (list
-;inferior
- '("^[#-]" . font-lock-comment-face))
- caml-font-lock-keywords))
-;; font-lock commands are similar for caml-mode and inferior-caml-mode
-(add-hook 'caml-mode-hook
- '(lambda ()
- (cond
- ((fboundp 'global-font-lock-mode)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults
- '(caml-font-lock-keywords nil nil ((?' . "w") (?_ . "w")))))
- (t
- (setq font-lock-keywords caml-font-lock-keywords)))
- (make-local-variable 'font-lock-keywords-only)
- (setq font-lock-keywords-only t)
- (font-lock-mode 1)))
+(defun caml-font-syntactic-face (s)
+ (let ((in-string (nth 3 s))
+ (in-comment (nth 4 s))
+ (start (nth 8 s)))
+ (cond
+ (in-string 'font-lock-string-face)
+ (in-comment
+ (goto-char start)
+ (cond
+ ((looking-at "(\\*\\*/\\*\\*)") 'caml-font-stop-face)
+ ((looking-at "(\\*\\*[^*]") 'caml-font-doccomment-face)
+ (t 'font-lock-comment-face))))))
-(defun inferior-caml-mode-font-hook ()
- (cond
- ((fboundp 'global-font-lock-mode)
- (make-local-variable 'font-lock-defaults)
- (setq font-lock-defaults
- '(inferior-caml-font-lock-keywords
- nil nil ((?' . "w") (?_ . "w")))))
- (t
- (setq font-lock-keywords inferior-caml-font-lock-keywords)))
- (make-local-variable 'font-lock-keywords-only)
- (setq font-lock-keywords-only t)
+
+;; font-lock commands are similar for caml-mode and inferior-caml-mode
+(defun caml-font-set-font-lock ()
+ (setq font-lock-defaults
+ '(caml-font-lock-keywords
+ nil nil nil nil
+ (font-lock-syntactic-face-function . caml-font-syntactic-face)))
(font-lock-mode 1))
+(add-hook 'caml-mode-hook 'caml-font-set-font-lock)
-(add-hook 'inferior-caml-mode-hooks 'inferior-caml-mode-font-hook)
+
+
+(defconst inferior-caml-font-lock-keywords
+ `(("^[#-]" . font-lock-comment-face)
+ ,@caml-font-lock-keywords))
+
+(defun inferior-caml-set-font-lock ()
+ (setq font-lock-defaults
+ '(inferior-caml-font-lock-keywords
+ nil nil nil nil
+ (font-lock-syntactic-face-function . caml-font-syntactic-face)))
+ (font-lock-mode 1))
+(add-hook 'inferior-caml-mode-hooks 'inferior-caml-set-font-lock)
(provide 'caml-font)
diff --git a/emacs/caml-types.el b/emacs/caml-types.el
index 71d47a54b..763edca7e 100644
--- a/emacs/caml-types.el
+++ b/emacs/caml-types.el
@@ -146,10 +146,8 @@ See `caml-types-location-re' for annotation file format.
(target-line (1+ (count-lines (point-min)
(caml-line-beginning-position))))
(target-bol (caml-line-beginning-position))
- (target-cnum (point))
- (type-file (concat (file-name-sans-extension (buffer-file-name))
- ".annot")))
- (caml-types-preprocess type-file)
+ (target-cnum (point)))
+ (caml-types-preprocess (buffer-file-name))
(setq caml-types-buffer (get-buffer-create caml-types-buffer-name))
(let* ((targ-loc (vector target-file target-line target-bol target-cnum))
(node (caml-types-find-location targ-loc "type" ()
@@ -323,28 +321,47 @@ See `caml-types-location-re' for annotation file format.
(delete-overlay caml-types-scope-ovl)
)))
-(defun caml-types-preprocess (type-file)
- (let* ((type-date (nth 5 (file-attributes type-file)))
- (target-file (file-name-nondirectory (buffer-file-name)))
+(defun caml-types-preprocess (target-path)
+ (let* ((type-path (caml-types-locate-type-file target-path))
+ (type-date (nth 5 (file-attributes (file-chase-links type-path))))
(target-date (nth 5 (file-attributes target-file))))
(unless (and caml-types-annotation-tree
type-date
caml-types-annotation-date
(not (caml-types-date< caml-types-annotation-date type-date)))
(if (and type-date target-date (caml-types-date< type-date target-date))
- (error (format "%s is more recent than %s" target-file type-file)))
+ (error (format "`%s' is more recent than `%s'" target-path type-path)))
(message "Reading annotation file...")
- (let* ((type-buf (caml-types-find-file type-file))
+ (let* ((type-buf (caml-types-find-file type-path))
(tree (with-current-buffer type-buf
(widen)
(goto-char (point-min))
- (caml-types-build-tree target-file))))
+ (caml-types-build-tree
+ (file-name-nondirectory target-path)))))
(setq caml-types-annotation-tree tree
caml-types-annotation-date type-date)
(kill-buffer type-buf)
(message "done"))
)))
+(defun caml-types-locate-type-file (target-path)
+ (let ((sibling (concat (file-name-sans-extension target-path) ".annot")))
+ (if (file-exists-p sibling)
+ sibling
+ (defun parent-dir (d) (file-name-directory (directory-file-name d)))
+ (let ((project-dir (file-name-directory sibling))
+ type-path)
+ (while (not (file-exists-p
+ (setq type-path
+ (expand-file-name
+ (file-relative-name sibling project-dir)
+ (expand-file-name "_build" project-dir)))))
+ (if (equal project-dir (parent-dir project-dir))
+ (error (concat "No annotation file. "
+ "You should compile with option \"-dtypes\".")))
+ (setq project-dir (parent-dir project-dir)))
+ type-path))))
+
(defun caml-types-date< (date1 date2)
(or (< (car date1) (car date2))
(and (= (car date1) (car date2))
@@ -553,7 +570,7 @@ See `caml-types-location-re' for annotation file format.
(with-current-buffer buf (toggle-read-only 1))
)
(t
- (error "No annotation file. You should compile with option \"-annot\"."))
+ (error (format "Can't read the annotation file `%s'" name)))
)
buf))
@@ -582,8 +599,6 @@ The function uses two overlays.
(set-buffer (window-buffer (caml-event-window event)))
(let* ((target-buf (current-buffer))
(target-file (file-name-nondirectory (buffer-file-name)))
- (type-file (concat (file-name-sans-extension (buffer-file-name))
- ".annot"))
(target-line) (target-bol)
target-pos
Left Right limits cnum node mes type
@@ -597,7 +612,7 @@ The function uses two overlays.
(select-window window)
(unwind-protect
(progn
- (caml-types-preprocess type-file)
+ (caml-types-preprocess (buffer-file-name))
(setq target-tree caml-types-annotation-tree)
(setq caml-types-buffer (get-buffer-create caml-types-buffer-name))
;; (message "Drag the mouse to explore types")
diff --git a/myocamlbuild.ml b/myocamlbuild.ml
index 75c17ba97..5a61f2eb0 100644
--- a/myocamlbuild.ml
+++ b/myocamlbuild.ml
@@ -1,3 +1,17 @@
+(***********************************************************************)
+(* *)
+(* Objective Caml *)
+(* *)
+(* Nicolas Pouillard, projet Gallium, INRIA Rocquencourt *)
+(* *)
+(* Copyright 2007 Institut National de Recherche en Informatique et *)
+(* en Automatique. All rights reserved. This file is distributed *)
+(* under the terms of the Q Public License version 1.0. *)
+(* *)
+(***********************************************************************)
+
+(* $Id$ *)
+
open Ocamlbuild_plugin
open Command
open Arch
@@ -24,7 +38,7 @@ let mkexe out files opts =
let mklib out files opts =
let s = Command.string_of_command_spec in
- Cmd(Sh(C.mklib out (s files) (s opts)))
+ Cmd(Sh(C.mklib out (s files) (s opts)))
let syslib x = A(C.syslib x);;
let syscamllib x =
@@ -67,7 +81,7 @@ let add_exe_if_exists a =
if Pathname.exists exe then exe else a;;
let convert_command_for_windows_shell spec =
- if not windows then spec else
+ if not windows then spec else
let rec self specs acc =
match specs with
| N :: specs -> self specs acc
@@ -149,7 +163,7 @@ dispatch begin function
"toplevel"; "typing"; "utils"]
in Ocamlbuild_pack.Configuration.parse_string
(sprintf "<{%s}/**>: not_hygienic, -traverse" patt)
-
+
| After_options ->
begin
Options.ocamlrun := ocamlrun;
@@ -563,8 +577,8 @@ rule "The numeric opcodes"
~prod:"bytecomp/opcodes.ml"
~dep:"byterun/instruct.h"
~insert:`top
- begin fun _ _ ->
- Cmd(Sh "sed -n -e '/^enum/p' -e 's/,//g' -e '/^ /p' byterun/instruct.h | \
+ begin fun _ _ ->
+ Cmd(Sh "sed -n -e '/^enum/p' -e 's/,//g' -e '/^ /p' byterun/instruct.h | \
awk -f ../tools/make-opcodes > bytecomp/opcodes.ml")
end;;
@@ -573,9 +587,9 @@ rule "tools/opnames.ml"
~dep:"byterun/instruct.h"
begin fun _ _ ->
Cmd(Sh"unset LC_ALL || : ; \
- unset LC_CTYPE || : ; \
- unset LC_COLLATE LANG || : ; \
- sed -e '/\\/\\*/d' \
+ unset LC_CTYPE || : ; \
+ unset LC_COLLATE LANG || : ; \
+ sed -e '/\\/\\*/d' \
-e '/^#/d' \
-e 's/enum \\(.*\\) {/let names_of_\\1 = [|/' \
-e 's/};$/ |]/' \
@@ -932,7 +946,7 @@ let builtins =
let labltk_support =
["support"; "rawwidget"; "widget"; "protocol"; "textvariable"; "timer"; "fileevent"; "camltkwrap"];;
-let labltk_generated_modules =
+let labltk_generated_modules =
["place"; "wm"; "imagephoto"; "canvas"; "button"; "text"; "label"; "scrollbar";
"image"; "encoding"; "pixmap"; "palette"; "font"; "message"; "menu"; "entry";
"listbox"; "focus"; "menubutton"; "pack"; "option"; "toplevel"; "frame";
diff --git a/ocamlbuild/examples/example_with_C/_tags b/ocamlbuild/examples/example_with_C/_tags
deleted file mode 100644
index 769cb463b..000000000
--- a/ocamlbuild/examples/example_with_C/_tags
+++ /dev/null
@@ -1 +0,0 @@
-<*caml.o>: output_obj
diff --git a/ocamlbuild/examples/example_with_C/fib.ml b/ocamlbuild/examples/example_with_C/fib.ml
deleted file mode 100644
index ef6dbd438..000000000
--- a/ocamlbuild/examples/example_with_C/fib.ml
+++ /dev/null
@@ -1,5 +0,0 @@
-let x = X.x
-
-let rec fib n = if n <= 1 then 1 else fib (n - 1) + fib (n - 2)
-
-let () = Callback.register "fib" fib
diff --git a/ocamlbuild/examples/example_with_C/fibwrap.c b/ocamlbuild/examples/example_with_C/fibwrap.c
deleted file mode 100644
index cc2104b67..000000000
--- a/ocamlbuild/examples/example_with_C/fibwrap.c
+++ /dev/null
@@ -1,7 +0,0 @@
- /* -*- C -*- */
-#include <caml/mlvalues.h>
-#include <caml/callback.h>
-int fib(int n)
-{
- return Int_val(caml_callback(*caml_named_value("fib"), Val_int(n)));
-}
diff --git a/ocamlbuild/examples/example_with_C/main.c b/ocamlbuild/examples/example_with_C/main.c
deleted file mode 100644
index c7f6bb5d2..000000000
--- a/ocamlbuild/examples/example_with_C/main.c
+++ /dev/null
@@ -1,10 +0,0 @@
- /* -*- C -*- */
-#include <stdio.h>
-#include <caml/callback.h>
-extern int fib(int);
-int main(int argc, char** argv)
-{
- caml_startup(argv);
- printf("fib(12) = %d\n", fib(12));
- return 0;
-}
diff --git a/ocamlbuild/examples/example_with_C/myocamlbuild.ml b/ocamlbuild/examples/example_with_C/myocamlbuild.ml
deleted file mode 100644
index f53df7e10..000000000
--- a/ocamlbuild/examples/example_with_C/myocamlbuild.ml
+++ /dev/null
@@ -1,35 +0,0 @@
-open Ocamlbuild_plugin;;
-open Command;;
-
-let cc = A"cc";;
-let ar = A"ar";;
-
-dispatch begin function
-| After_rules ->
- let libasmrun = !*Ocamlbuild_pack.Ocaml_utils.stdlib_dir/"libasmrun.a" in
-
- flag ["ocaml"; "link"; "output_obj"] (A"-output-obj");
-
- rule "output C obj"
- ~deps:["%.cmx"; "%.o"]
- ~prod:"%caml.o"
- (Ocamlbuild_pack.Ocaml_compiler.native_link "%.cmx" "%caml.o");
-
- rule "build C lib"
- ~deps:["%wrap.o"; "%caml.o"]
- ~prod:"lib%.a"
- begin fun env _ ->
- let wrap_o = env "%wrap.o" and caml_o = env "%caml.o"
- and lib_a = env "lib%.a" in
- Seq[cp libasmrun lib_a;
- Cmd(S[ar; A"r"; Px lib_a; P caml_o; P wrap_o])]
- end;
- rule "build main"
- ~deps:["libfib.a"; "main.o"]
- ~prod:"main"
- begin fun _ _ ->
- Cmd(S[cc; P"main.o"; P"libfib.a"; A"-o"; Px"main"])
- end;
-| _ -> ()
-end
-
diff --git a/ocamlbuild/examples/example_with_C/x.ml b/ocamlbuild/examples/example_with_C/x.ml
deleted file mode 100644
index 7fecab12d..000000000
--- a/ocamlbuild/examples/example_with_C/x.ml
+++ /dev/null
@@ -1 +0,0 @@
-let x = 42
diff --git a/ocamlbuild/start.sh b/ocamlbuild/start.sh
index dbbe72c52..662392b5f 100755
--- a/ocamlbuild/start.sh
+++ b/ocamlbuild/start.sh
@@ -1,4 +1,19 @@
#!/bin/sh
+
+#########################################################################
+# #
+# Objective Caml #
+# #
+# Nicolas Pouillard, projet Gallium, INRIA Rocquencourt #
+# #
+# Copyright 2007 Institut National de Recherche en Informatique et #
+# en Automatique. All rights reserved. This file is distributed #
+# under the terms of the Q Public License version 1.0. #
+# #
+#########################################################################
+
+# $Id$
+
set -e
set -x
rm -rf _start
diff --git a/ocamldoc/Makefile b/ocamldoc/Makefile
index 4e9256b24..14a596763 100644
--- a/ocamldoc/Makefile
+++ b/ocamldoc/Makefile
@@ -334,7 +334,7 @@ autotest_stdlib: dummy
clean:: dummy
@rm -f *~ \#*\#
- @rm -f $(OCAMLDOC)$(EXE) $(OCAMLDOC_OPT) *.cma *.cmxa *.cmo *.cmi *.cmx *.a *.o
+ @rm -f $(OCAMLDOC) $(OCAMLDOC_OPT) *.cma *.cmxa *.cmo *.cmi *.cmx *.a *.o
@rm -f odoc_parser.output odoc_text_parser.output
@rm -f odoc_lexer.ml odoc_text_lexer.ml odoc_see_lexer.ml odoc_ocamlhtml.ml
@rm -f odoc_parser.ml odoc_parser.mli odoc_text_parser.ml odoc_text_parser.mli
diff --git a/ocamldoc/odoc_ocamlhtml.mll b/ocamldoc/odoc_ocamlhtml.mll
index d935db9a4..fd8aa6091 100644
--- a/ocamldoc/odoc_ocamlhtml.mll
+++ b/ocamldoc/odoc_ocamlhtml.mll
@@ -14,7 +14,7 @@
(* $Id$ *)
(** Generation of html code to display OCaml code. *)
-open Lexing
+open Lexing
exception Fatal_error
@@ -31,17 +31,17 @@ type error =
exception Error of error * int * int
-let base_escape_strings = [
- ("&", "&amp;") ;
- ("<", "&lt;") ;
- (">", "&gt;") ;
-]
+let base_escape_strings = [
+ ("&", "&amp;") ;
+ ("<", "&lt;") ;
+ (">", "&gt;") ;
+]
let pre_escape_strings = [
(" ", "&nbsp;") ;
("\n", "<br>\n") ;
("\t", "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;") ;
- ]
+ ]
let pre = ref false
@@ -49,7 +49,7 @@ let fmt = ref Format.str_formatter
(** Escape the strings which would clash with html syntax,
and some other strings if we want to get a PRE style.*)
-let escape s =
+let escape s =
List.fold_left
(fun acc -> fun (s, s2) -> Str.global_replace (Str.regexp s) s2 acc)
s
@@ -64,7 +64,7 @@ let escape_base s =
(** The output functions *)
-let print ?(esc=true) s =
+let print ?(esc=true) s =
Format.pp_print_string !fmt (if esc then escape s else s)
;;
@@ -81,7 +81,7 @@ let create_hashtable size init =
tbl
(** The function used to return html code for the given comment body. *)
-let html_of_comment = ref
+let html_of_comment = ref
(fun (s : string) -> "<b>Odoc_ocamlhtml.html_of_comment not initialized</b>")
let keyword_table =
@@ -160,6 +160,7 @@ let margin = ref 0
let comment_buffer = Buffer.create 32
let reset_comment_buffer () = Buffer.reset comment_buffer
let store_comment_char = Buffer.add_char comment_buffer
+let add_comment_string = Buffer.add_string comment_buffer
let make_margin () =
let rec iter n =
@@ -171,14 +172,14 @@ let make_margin () =
let print_comment () =
let s = Buffer.contents comment_buffer in
let len = String.length s in
- let code =
+ let code =
if len < 1 then
"<span class=\""^comment_class^"\">(*"^(escape s)^"*)</span>"
else
- match s.[0] with
- '*' ->
+ match s.[0] with
+ '*' ->
(
- try
+ try
let html = !html_of_comment (String.sub s 1 (len-1)) in
"</code><table><tr><td>"^(make_margin ())^"</td><td>"^
"<span class=\""^comment_class^"\">"^
@@ -199,7 +200,7 @@ let print_comment () =
let string_buffer = Buffer.create 32
let reset_string_buffer () = Buffer.reset string_buffer
let store_string_char = Buffer.add_char string_buffer
-let get_stored_string () =
+let get_stored_string () =
let s = Buffer.contents string_buffer in
String.escaped s
@@ -215,7 +216,7 @@ let char_for_backslash = function
let char_for_decimal_code lexbuf i =
let c = 100 * (Char.code(Lexing.lexeme_char lexbuf i) - 48) +
10 * (Char.code(Lexing.lexeme_char lexbuf (i+1)) - 48) +
- (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48) in
+ (Char.code(Lexing.lexeme_char lexbuf (i+2)) - 48) in
Char.chr(c land 0xFF)
(** To store the position of the beginning of a string and comment *)
@@ -245,7 +246,7 @@ let report_error ppf = function
let blank = [' ' '\010' '\013' '\009' '\012']
let lowercase = ['a'-'z' '\223'-'\246' '\248'-'\255' '_']
let uppercase = ['A'-'Z' '\192'-'\214' '\216'-'\222']
-let identchar =
+let identchar =
['A'-'Z' 'a'-'z' '_' '\192'-'\214' '\216'-'\246' '\248'-'\255' '\'' '0'-'9']
let symbolchar =
['!' '$' '%' '&' '*' '+' '-' '.' '/' ':' '<' '=' '>' '?' '@' '^' '|' '~']
@@ -258,17 +259,17 @@ let float_literal =
rule token = parse
blank
- {
+ {
let s = Lexing.lexeme lexbuf in
(
match s with
- " " -> incr margin
+ " " -> incr margin
| "\t" -> margin := !margin + 8
| "\n" -> margin := 0
| _ -> ()
);
print s;
- token lexbuf
+ token lexbuf
}
| "_"
{ print "_" ; token lexbuf }
@@ -320,9 +321,9 @@ rule token = parse
{ print_class string_class (Lexing.lexeme lexbuf ) ;
token lexbuf }
| "(*"
- {
+ {
reset_comment_buffer ();
- comment_start_pos := [Lexing.lexeme_start lexbuf];
+ comment_start_pos := [Lexing.lexeme_start lexbuf];
comment lexbuf ;
print_comment ();
token lexbuf }
@@ -335,18 +336,18 @@ rule token = parse
}
| "*)"
{ lexbuf.Lexing.lex_curr_pos <- lexbuf.Lexing.lex_curr_pos - 1;
- lexbuf.Lexing.lex_curr_p <-
+ lexbuf.Lexing.lex_curr_p <-
{ lexbuf.Lexing.lex_curr_p with
pos_cnum = lexbuf.Lexing.lex_curr_p.pos_cnum - 1
} ;
print (Lexing.lexeme lexbuf) ;
- token lexbuf
+ token lexbuf
}
| "#" [' ' '\t']* ['0'-'9']+ [^ '\n' '\r'] * ('\n' | '\r' | "\r\n")
(* # linenum ... *)
- {
+ {
print (Lexing.lexeme lexbuf);
- token lexbuf
+ token lexbuf
}
| "#" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
| "&" { print_class kwsign_class (Lexing.lexeme lexbuf) ; token lexbuf }
@@ -419,7 +420,7 @@ and comment = parse
{ match !comment_start_pos with
| [] -> assert false
| [x] -> comment_start_pos := []
- | _ :: l ->
+ | _ :: l ->
store_comment_char '*';
store_comment_char ')';
comment_start_pos := l;
@@ -429,32 +430,33 @@ and comment = parse
{ reset_string_buffer();
string_start_pos := Lexing.lexeme_start lexbuf;
store_comment_char '"';
- begin try string lexbuf
- with Error (Unterminated_string, _, _) ->
+ begin
+ try string lexbuf; add_comment_string ((get_stored_string()^"\""))
+ with Error (Unterminated_string, _, _) ->
let st = List.hd !comment_start_pos in
raise (Error (Unterminated_string_in_comment, st, st + 2))
end;
comment lexbuf }
| "''"
- {
+ {
store_comment_char '\'';
store_comment_char '\'';
comment lexbuf }
| "'" [^ '\\' '\''] "'"
- {
+ {
store_comment_char '\'';
store_comment_char (Lexing.lexeme_char lexbuf 1);
store_comment_char '\'';
comment lexbuf }
| "'\\" ['\\' '\'' 'n' 't' 'b' 'r'] "'"
- {
+ {
store_comment_char '\'';
store_comment_char '\\';
store_comment_char(char_for_backslash(Lexing.lexeme_char lexbuf 1)) ;
store_comment_char '\'';
comment lexbuf }
| "'\\" ['0'-'9'] ['0'-'9'] ['0'-'9'] "'"
- {
+ {
store_comment_char '\'';
store_comment_char '\\';
store_comment_char(char_for_decimal_code lexbuf 1);
@@ -497,10 +499,10 @@ let html_of_code b ?(with_pre=true) code =
fmt := Format.formatter_of_buffer buf ;
pre := with_pre;
margin := 0;
-
+
let start = "<code class=\""^code_class^"\">" in
let ending = "</code>" in
- let html =
+ let html =
(
try
print ~esc: false start ;
@@ -510,8 +512,8 @@ let html_of_code b ?(with_pre=true) code =
Format.pp_print_flush !fmt () ;
Buffer.contents buf
with
- _ ->
- (* flush str_formatter because we already output
+ _ ->
+ (* flush str_formatter because we already output
something in it *)
Format.pp_print_flush !fmt () ;
start^code^ending
@@ -527,4 +529,4 @@ let html_of_code b ?(with_pre=true) code =
Buffer.add_string b html
-}
+}
diff --git a/otherlibs/labltk/support/tkthread.ml b/otherlibs/labltk/support/tkthread.ml
index 04dcc74c5..ecdf61460 100644
--- a/otherlibs/labltk/support/tkthread.ml
+++ b/otherlibs/labltk/support/tkthread.ml
@@ -20,20 +20,18 @@ let with_jobs f =
Mutex.lock m; let y = f jobs in Mutex.unlock m; y
let loop_id = ref None
-let reset () = loop_id := None
-let cannot_sync () =
- match !loop_id with None -> true
- | Some id -> Thread.id (Thread.self ()) = id
-
let gui_safe () =
!loop_id = Some(Thread.id (Thread.self ()))
+let running () =
+ !loop_id <> None
let has_jobs () = not (with_jobs Queue.is_empty)
let n_jobs () = with_jobs Queue.length
let do_next_job () = with_jobs Queue.take ()
let async j x = with_jobs (Queue.add (fun () -> j x))
let sync f x =
- if cannot_sync () then f x else
+ if !loop_id = None then failwith "Tkthread.sync";
+ if gui_safe () then f x else
let m = Mutex.create () in
let res = ref None in
Mutex.lock m;
@@ -62,6 +60,8 @@ let thread_main () =
raise exn
let start () =
- Thread.create thread_main ()
+ let th = Thread.create thread_main () in
+ loop_id := Some (Thread.id th);
+ th
let top = Widget.default_toplevel
diff --git a/otherlibs/labltk/support/tkthread.mli b/otherlibs/labltk/support/tkthread.mli
index 88883a5db..7e871d9cd 100644
--- a/otherlibs/labltk/support/tkthread.mli
+++ b/otherlibs/labltk/support/tkthread.mli
@@ -19,7 +19,7 @@
(** Start the main loop in a new GUI thread. Do not use recursively. *)
val start : unit -> Thread.t
-(** The actual function executed in the new thread *)
+(** The actual function executed in the GUI thread *)
val thread_main : unit -> unit
(** The toplevel widget (an alias of [Widget.default_toplevel]) *)
val top : Widget.toplevel Widget.widget
@@ -33,11 +33,14 @@ val top : Widget.toplevel Widget.widget
With sync, beware of deadlocks!
*)
-(** Add an asynchronous job (to do in the main thread) *)
+(** Add an asynchronous job (to do in the GUI thread) *)
val async : ('a -> unit) -> 'a -> unit
-(** Add a synchronous job (to do in the main thread) *)
+(** Add a synchronous job (to do in the GUI thread).
+ Raise [Failure "Tkthread.sync"] if there is no such thread. *)
val sync : ('a -> 'b) -> 'a -> 'b
(** Whether the current thread is the GUI thread.
Note that when using X11 it is generally safe to call
most Tk functions from other threads too. *)
val gui_safe : unit -> bool
+(** Whether a GUI thread is running *)
+val running : unit -> bool
diff --git a/otherlibs/num/nat_stubs.c b/otherlibs/num/nat_stubs.c
index f5e101548..e41abff17 100644
--- a/otherlibs/num/nat_stubs.c
+++ b/otherlibs/num/nat_stubs.c
@@ -120,7 +120,7 @@ CAMLprim value is_digit_zero(value nat, value ofs)
CAMLprim value is_digit_normalized(value nat, value ofs)
{
return
- Val_bool(Digit_val(nat, Long_val(ofs)) & (1L << (BNG_BITS_PER_DIGIT-1)));
+ Val_bool(Digit_val(nat, Long_val(ofs)) & ((bngdigit)1 << (BNG_BITS_PER_DIGIT-1)));
}
CAMLprim value is_digit_odd(value nat, value ofs)
@@ -341,7 +341,7 @@ static void serialize_nat(value nat,
#ifdef ARCH_SIXTYFOUR
len = len * 2; /* two 32-bit words per 64-bit digit */
- if (len >= (1L << 32))
+ if (len >= ((mlsize_t)1 << 32))
failwith("output_value: nat too big");
#endif
serialize_int_4((int32) len);
diff --git a/otherlibs/str/str.ml b/otherlibs/str/str.ml
index 31b623284..080efae9f 100644
--- a/otherlibs/str/str.ml
+++ b/otherlibs/str/str.ml
@@ -669,9 +669,9 @@ and replace_first expr repl text =
let search_forward_progress expr text start =
let pos = search_forward expr text start in
- if match_end() = start && start < String.length text
- then search_forward expr text (start + 1)
- else pos
+ if match_end() > start then pos
+ else if start < String.length text then search_forward expr text (start + 1)
+ else raise Not_found
let bounded_split expr text num =
let start =
diff --git a/otherlibs/systhreads/posix.c b/otherlibs/systhreads/posix.c
index 0e5354241..7c4a572a6 100644
--- a/otherlibs/systhreads/posix.c
+++ b/otherlibs/systhreads/posix.c
@@ -801,7 +801,7 @@ static void decode_sigset(value vset, sigset_t * set)
{
sigemptyset(set);
while (vset != Val_int(0)) {
- int sig = convert_signal_number(Int_val(Field(vset, 0)));
+ int sig = caml_convert_signal_number(Int_val(Field(vset, 0)));
sigaddset(set, sig);
vset = Field(vset, 1);
}
@@ -818,9 +818,9 @@ static value encode_sigset(sigset_t * set)
Begin_root(res)
for (i = 1; i < NSIG; i++)
- if (sigismember(set, i)) {
+ if (sigismember(set, i) > 0) {
value newcons = alloc_small(2, 0);
- Field(newcons, 0) = Val_int(i);
+ Field(newcons, 0) = Val_int(caml_rev_convert_signal_number(i));
Field(newcons, 1) = res;
res = newcons;
}
diff --git a/otherlibs/systhreads/thread.mli b/otherlibs/systhreads/thread.mli
index af274bfc8..8394a47bc 100644
--- a/otherlibs/systhreads/thread.mli
+++ b/otherlibs/systhreads/thread.mli
@@ -33,10 +33,10 @@ val create : ('a -> 'b) -> 'a -> t
result of the application [funct arg] is discarded and not
directly accessible to the parent thread. *)
-external self : unit -> t = "caml_thread_self"
+val self : unit -> t
(** Return the thread currently executing. *)
-external id : t -> int = "caml_thread_id"
+val id : t -> int
(** Return the identifier of the given thread. A thread identifier
is an integer that identifies uniquely the thread.
It can be used to build data structures indexed by threads. *)
@@ -54,7 +54,7 @@ val delay: float -> unit
[d] seconds. The other program threads continue to run during
this time. *)
-external join : t -> unit = "caml_thread_join"
+val join : t -> unit
(** [join th] suspends the execution of the calling thread
until the thread [th] has terminated. *)
diff --git a/otherlibs/unix/access.c b/otherlibs/unix/access.c
index d7065c68e..0c0c5fc1a 100644
--- a/otherlibs/unix/access.c
+++ b/otherlibs/unix/access.c
@@ -31,7 +31,7 @@
# else
# define R_OK 4/* test for read permission */
# define W_OK 2/* test for write permission */
-# define X_OK 1/* test for execute (search) permission */
+# define X_OK 4/* test for execute permission - not implemented in Win32 */
# define F_OK 0/* test for presence of file */
# endif
#endif
diff --git a/otherlibs/unix/signals.c b/otherlibs/unix/signals.c
index b244f8af6..c388b1393 100644
--- a/otherlibs/unix/signals.c
+++ b/otherlibs/unix/signals.c
@@ -24,7 +24,7 @@
#include "unixsupport.h"
#ifndef NSIG
-#define NSIG 32
+#define NSIG 64
#endif
#ifdef POSIX_SIGNALS
@@ -33,7 +33,7 @@ static void decode_sigset(value vset, sigset_t * set)
{
sigemptyset(set);
while (vset != Val_int(0)) {
- int sig = convert_signal_number(Int_val(Field(vset, 0)));
+ int sig = caml_convert_signal_number(Int_val(Field(vset, 0)));
sigaddset(set, sig);
vset = Field(vset, 1);
}
@@ -46,9 +46,9 @@ static value encode_sigset(sigset_t * set)
Begin_root(res)
for (i = 1; i < NSIG; i++)
- if (sigismember(set, i)) {
+ if (sigismember(set, i) > 0) {
value newcons = alloc_small(2, 0);
- Field(newcons, 0) = Val_int(i);
+ Field(newcons, 0) = Val_int(caml_rev_convert_signal_number(i));
Field(newcons, 1) = res;
res = newcons;
}
diff --git a/otherlibs/unix/unix.mli b/otherlibs/unix/unix.mli
index cf73b4835..acc0d74a4 100644
--- a/otherlibs/unix/unix.mli
+++ b/otherlibs/unix/unix.mli
@@ -758,7 +758,8 @@ val times : unit -> process_times
val utimes : string -> float -> float -> unit
(** Set the last access time (second arg) and last modification time
(third arg) for a file. Times are expressed in seconds from
- 00:00:00 GMT, Jan. 1, 1970. *)
+ 00:00:00 GMT, Jan. 1, 1970. A time of [0.0] is interpreted as the
+ current time. *)
type interval_timer =
ITIMER_REAL
diff --git a/otherlibs/unix/unixLabels.mli b/otherlibs/unix/unixLabels.mli
index 4ea1f4c86..11fe09350 100644
--- a/otherlibs/unix/unixLabels.mli
+++ b/otherlibs/unix/unixLabels.mli
@@ -383,7 +383,7 @@ module LargeFile :
(** File operations on large files.
This sub-module provides 64-bit variants of the functions
{!UnixLabels.lseek} (for positioning a file descriptor),
- {!UnixLabels.truncate} and {!UnixLabels.ftruncate}
+ {!UnixLabels.truncate} and {!UnixLabels.ftruncate}
(for changing the size of a file),
and {!UnixLabels.stat}, {!UnixLabels.lstat} and {!UnixLabels.fstat}
(for obtaining information on files). These alternate functions represent
@@ -577,23 +577,23 @@ val open_process_full :
and standard error of the command. *)
val close_process_in : in_channel -> process_status
-(** Close channels opened by {!UnixLabels.open_process_in},
+(** Close channels opened by {!UnixLabels.open_process_in},
wait for the associated command to terminate,
and return its termination status. *)
val close_process_out : out_channel -> process_status
-(** Close channels opened by {!UnixLabels.open_process_out},
+(** Close channels opened by {!UnixLabels.open_process_out},
wait for the associated command to terminate,
and return its termination status. *)
val close_process : in_channel * out_channel -> process_status
-(** Close channels opened by {!UnixLabels.open_process},
+(** Close channels opened by {!UnixLabels.open_process},
wait for the associated command to terminate,
and return its termination status. *)
val close_process_full :
in_channel * out_channel * in_channel -> process_status
-(** Close channels opened by {!UnixLabels.open_process_full},
+(** Close channels opened by {!UnixLabels.open_process_full},
wait for the associated command to terminate,
and return its termination status. *)
@@ -675,7 +675,7 @@ val kill : pid:int -> signal:int -> unit
(** [kill pid sig] sends signal number [sig] to the process
with id [pid]. *)
-type sigprocmask_command = Unix.sigprocmask_command =
+type sigprocmask_command = Unix.sigprocmask_command =
SIG_SETMASK
| SIG_BLOCK
| SIG_UNBLOCK
@@ -913,7 +913,7 @@ type socket_type = Unix.socket_type =
(** The type of socket kinds, specifying the semantics of
communications. *)
-type sockaddr = Unix.sockaddr =
+type sockaddr = Unix.sockaddr =
ADDR_UNIX of string
| ADDR_INET of inet_addr * int
(** The type of socket addresses. [ADDR_UNIX name] is a socket
@@ -971,11 +971,11 @@ val getsockname : file_descr -> sockaddr
val getpeername : file_descr -> sockaddr
(** Return the address of the host connected to the given socket. *)
-type msg_flag = Unix.msg_flag =
+type msg_flag = Unix.msg_flag =
MSG_OOB
| MSG_DONTROUTE
| MSG_PEEK
-(** The flags for {!UnixLabels.recv}, {!UnixLabels.recvfrom},
+(** The flags for {!UnixLabels.recv}, {!UnixLabels.recvfrom},
{!UnixLabels.send} and {!UnixLabels.sendto}. *)
val recv :
@@ -1271,7 +1271,7 @@ val tcgetattr : file_descr -> terminal_io
(** Return the status of the terminal referred to by the given
file descriptor. *)
-type setattr_when = Unix.setattr_when =
+type setattr_when = Unix.setattr_when =
TCSANOW
| TCSADRAIN
| TCSAFLUSH
@@ -1295,7 +1295,7 @@ val tcdrain : file_descr -> unit
(** Waits until all output written on the given file descriptor
has been transmitted. *)
-type flush_queue = Unix.flush_queue =
+type flush_queue = Unix.flush_queue =
TCIFLUSH
| TCOFLUSH
| TCIOFLUSH
@@ -1307,7 +1307,7 @@ val tcflush : file_descr -> mode:flush_queue -> unit
[TCOFLUSH] flushes data written but not transmitted, and
[TCIOFLUSH] flushes both. *)
-type flow_action = Unix.flow_action =
+type flow_action = Unix.flow_action =
TCOOFF
| TCOON
| TCIOFF
diff --git a/otherlibs/win32unix/createprocess.c b/otherlibs/win32unix/createprocess.c
index 8a92d18f0..d91d707b4 100644
--- a/otherlibs/win32unix/createprocess.c
+++ b/otherlibs/win32unix/createprocess.c
@@ -62,7 +62,7 @@ value win_create_process_native(value cmd, value cmdline, value env,
CloseHandle(pi.hThread);
/* Return the process handle as pseudo-PID
(this is consistent with the wait() emulation in the MSVC C library */
- return Val_int(pi.hProcess);
+ return Val_long(pi.hProcess);
}
CAMLprim value win_create_process(value * argv, int argn)
diff --git a/otherlibs/win32unix/open.c b/otherlibs/win32unix/open.c
index 76e73e3ae..f2f334bbb 100644
--- a/otherlibs/win32unix/open.c
+++ b/otherlibs/win32unix/open.c
@@ -18,12 +18,13 @@
#include "unixsupport.h"
#include <fcntl.h>
-static int open_access_flags[8] = {
- GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE, 0, 0, 0, 0, 0,
+static int open_access_flags[12] = {
+ GENERIC_READ, GENERIC_WRITE, GENERIC_READ|GENERIC_WRITE,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0
};
-static int open_create_flags[8] = {
- 0, 0, 0, 0, 0, O_CREAT, O_TRUNC, O_EXCL
+static int open_create_flags[12] = {
+ 0, 0, 0, 0, 0, O_CREAT, O_TRUNC, O_EXCL, 0, 0, 0, 0
};
CAMLprim value unix_open(value path, value flags, value perm)
diff --git a/otherlibs/win32unix/winwait.c b/otherlibs/win32unix/winwait.c
index ad510c4b4..895a6926b 100644
--- a/otherlibs/win32unix/winwait.c
+++ b/otherlibs/win32unix/winwait.c
@@ -63,6 +63,8 @@ CAMLprim value win_waitpid(value vflags, value vpid_req)
}
if (status == STILL_ACTIVE)
return alloc_process_status((HANDLE) 0, 0);
- else
+ else {
+ CloseHandle(pid_req);
return alloc_process_status(pid_req, status);
+ }
}
diff --git a/parsing/location.ml b/parsing/location.ml
index 1516b16d7..15b074acd 100644
--- a/parsing/location.ml
+++ b/parsing/location.ml
@@ -70,9 +70,10 @@ let status = ref Terminfo.Uninitialised
let num_loc_lines = ref 0 (* number of lines already printed after input *)
-(* Highlight the location using standout mode. *)
+(* Highlight the locations using standout mode. *)
let highlight_terminfo ppf num_lines lb loc1 loc2 =
+ Format.pp_print_flush ppf (); (* avoid mixing Format and normal output *)
(* Char 0 is at offset -lb.lex_abs_pos in lb.lex_buffer. *)
let pos0 = -lb.lex_abs_pos in
(* Do nothing if the buffer does not contain the whole phrase. *)
@@ -125,7 +126,7 @@ let highlight_dumb ppf lb loc =
Format.fprintf ppf "Characters %i-%i:@."
loc.loc_start.pos_cnum loc.loc_end.pos_cnum;
(* Print the input, underlining the location *)
- print_string " ";
+ Format.pp_print_string ppf " ";
let line = ref 0 in
let pos_at_bol = ref 0 in
for pos = 0 to end_pos do
@@ -133,34 +134,34 @@ let highlight_dumb ppf lb loc =
if c <> '\n' then begin
if !line = !line_start && !line = !line_end then
(* loc is on one line: print whole line *)
- print_char c
+ Format.pp_print_char ppf c
else if !line = !line_start then
(* first line of multiline loc: print ... before loc_start *)
if pos < loc.loc_start.pos_cnum
- then print_char '.'
- else print_char c
+ then Format.pp_print_char ppf '.'
+ else Format.pp_print_char ppf c
else if !line = !line_end then
(* last line of multiline loc: print ... after loc_end *)
if pos < loc.loc_end.pos_cnum
- then print_char c
- else print_char '.'
+ then Format.pp_print_char ppf c
+ else Format.pp_print_char ppf '.'
else if !line > !line_start && !line < !line_end then
(* intermediate line of multiline loc: print whole line *)
- print_char c
+ Format.pp_print_char ppf c
end else begin
if !line = !line_start && !line = !line_end then begin
(* loc is on one line: underline location *)
- print_string "\n ";
+ Format.fprintf ppf "@. ";
for i = !pos_at_bol to loc.loc_start.pos_cnum - 1 do
- print_char ' '
+ Format.pp_print_char ppf ' '
done;
for i = loc.loc_start.pos_cnum to loc.loc_end.pos_cnum - 1 do
- print_char '^'
+ Format.pp_print_char ppf '^'
done
end;
if !line >= !line_start && !line <= !line_end then begin
- print_char '\n';
- if pos < loc.loc_end.pos_cnum then print_string " "
+ Format.fprintf ppf "@.";
+ if pos < loc.loc_end.pos_cnum then Format.pp_print_string ppf " "
end;
incr line;
pos_at_bol := pos + 1;
diff --git a/parsing/parser.mly b/parsing/parser.mly
index e30a6a3c9..e5f7133d3 100644
--- a/parsing/parser.mly
+++ b/parsing/parser.mly
@@ -443,8 +443,8 @@ structure_item:
{ match $3 with
[{ppat_desc = Ppat_any}, exp] -> mkstr(Pstr_eval exp)
| _ -> mkstr(Pstr_value($2, List.rev $3)) }
- | EXTERNAL val_ident_colon core_type EQUAL primitive_declaration
- { mkstr(Pstr_primitive($2, {pval_type = $3; pval_prim = $5})) }
+ | EXTERNAL val_ident COLON core_type EQUAL primitive_declaration
+ { mkstr(Pstr_primitive($2, {pval_type = $4; pval_prim = $6})) }
| TYPE type_declarations
{ mkstr(Pstr_type(List.rev $2)) }
| EXCEPTION UIDENT constructor_arguments
@@ -507,10 +507,10 @@ signature:
| signature signature_item SEMISEMI { $2 :: $1 }
;
signature_item:
- VAL val_ident_colon core_type
- { mksig(Psig_value($2, {pval_type = $3; pval_prim = []})) }
- | EXTERNAL val_ident_colon core_type EQUAL primitive_declaration
- { mksig(Psig_value($2, {pval_type = $3; pval_prim = $5})) }
+ VAL val_ident COLON core_type
+ { mksig(Psig_value($2, {pval_type = $4; pval_prim = []})) }
+ | EXTERNAL val_ident COLON core_type EQUAL primitive_declaration
+ { mksig(Psig_value($2, {pval_type = $4; pval_prim = $6})) }
| TYPE type_declarations
{ mksig(Psig_type(List.rev $2)) }
| EXCEPTION UIDENT constructor_arguments
@@ -666,8 +666,6 @@ concrete_method :
{ $3, $2, ghexp(Pexp_poly ($4, None)), symbol_rloc () }
| METHOD private_flag label COLON poly_type EQUAL seq_expr
{ $3, $2, ghexp(Pexp_poly($7,Some $5)), symbol_rloc () }
- | METHOD private_flag LABEL poly_type EQUAL seq_expr
- { $3, $2, ghexp(Pexp_poly($6,Some $4)), symbol_rloc () }
;
/* Class types */
@@ -1412,11 +1410,6 @@ val_ident:
LIDENT { $1 }
| LPAREN operator RPAREN { $2 }
;
-val_ident_colon:
- LIDENT COLON { $1 }
- | LPAREN operator RPAREN COLON { $2 }
- | LABEL { $1 }
-;
operator:
PREFIXOP { $1 }
| INFIXOP0 { $1 }
diff --git a/stdlib/arg.ml b/stdlib/arg.ml
index dd6c51753..009e20375 100644
--- a/stdlib/arg.ml
+++ b/stdlib/arg.ml
@@ -65,7 +65,7 @@ let make_symlist prefix sep suffix l =
let print_spec buf (key, spec, doc) =
match spec with
- | Symbol (l, _) -> bprintf buf " %s %s %s\n" key (make_symlist "{" "|" "}" l)
+ | Symbol (l, _) -> bprintf buf " %s %s%s\n" key (make_symlist "{" "|" "}" l)
doc
| _ -> bprintf buf " %s %s\n" key doc
;;
@@ -225,13 +225,18 @@ let rec second_word s =
with Not_found -> len
;;
-let max_arg_len cur (kwd, _, doc) =
- max cur (String.length kwd + second_word doc)
+let max_arg_len cur (kwd, spec, doc) =
+ match spec with
+ | Symbol _ -> max cur (String.length kwd)
+ | _ -> max cur (String.length kwd + second_word doc)
;;
let add_padding len ksd =
match ksd with
- | (_, Symbol _, _) -> ksd
+ | (kwd, (Symbol (l, _) as spec), msg) ->
+ let cutcol = second_word msg in
+ let spaces = String.make (len - cutcol + 3) ' ' in
+ (kwd, spec, "\n" ^ spaces ^ msg)
| (kwd, spec, msg) ->
let cutcol = second_word msg in
let spaces = String.make (len - String.length kwd - cutcol) ' ' in
diff --git a/stdlib/arg.mli b/stdlib/arg.mli
index bc33d239f..4e5ed08d1 100644
--- a/stdlib/arg.mli
+++ b/stdlib/arg.mli
@@ -125,7 +125,7 @@ val align: (key * spec * doc) list -> (key * spec * doc) list;;
space, according to the length of the keyword. Use a
space as the first character in a doc string if you want to
align the whole string. The doc strings corresponding to
- [Symbol] arguments are not aligned. *)
+ [Symbol] arguments are aligned on the next line. *)
val current : int ref
(** Position (in {!Sys.argv}) of the argument being processed. You can
diff --git a/stdlib/camlinternalMod.ml b/stdlib/camlinternalMod.ml
index 17419aef5..12a77cc8f 100644
--- a/stdlib/camlinternalMod.ml
+++ b/stdlib/camlinternalMod.ml
@@ -48,8 +48,16 @@ let rec update_mod shape o n =
then begin overwrite o n; Obj.truncate o (Obj.size n) (* PR #4008 *) end
else overwrite o (Obj.repr (fun x -> (Obj.obj n : _ -> _) x))
| Lazy ->
- assert (Obj.tag n = Obj.lazy_tag);
- overwrite o n
+ if Obj.tag n = Obj.lazy_tag then
+ Obj.set_field o 0 (Obj.field n 0)
+ else if Obj.tag n = Obj.forward_tag then begin (* PR#4316 *)
+ Obj.set_tag o Obj.forward_tag;
+ Obj.set_field o 0 (Obj.field n 0)
+ end else begin
+ (* forwarding pointer was shortcut by GC *)
+ Obj.set_tag o Obj.forward_tag;
+ Obj.set_field o 0 n
+ end
| Class ->
assert (Obj.tag n = 0 && Obj.size n = 4);
overwrite o n
diff --git a/stdlib/camlinternalOO.ml b/stdlib/camlinternalOO.ml
index 2205a37fe..2ffa71c0a 100644
--- a/stdlib/camlinternalOO.ml
+++ b/stdlib/camlinternalOO.ml
@@ -262,7 +262,7 @@ let new_variable table name =
try Vars.find name table.vars
with Not_found ->
let index = new_slot table in
- table.vars <- Vars.add name index table.vars;
+ if name <> "" then table.vars <- Vars.add name index table.vars;
index
let to_array arr =
diff --git a/stdlib/format.ml b/stdlib/format.ml
index 7f6fcc4a4..f0af85a79 100644
--- a/stdlib/format.ml
+++ b/stdlib/format.ml
@@ -67,7 +67,9 @@ and tblock = Pp_tbox of int list ref (* Tabulation box *)
size is set when the size of the block is known
len is the declared length of the token. *)
type pp_queue_elem = {
- mutable elem_size : size; token : pp_token; length : int
+ mutable elem_size : size;
+ token : pp_token;
+ length : int;
};;
(* Scan stack:
@@ -82,75 +84,80 @@ type pp_scan_elem = Scan_elem of int * pp_queue_elem;;
type pp_format_elem = Format_elem of block_type * int;;
(* General purpose queues, used in the formatter. *)
-type 'a queue_elem = | Nil | Cons of 'a queue_cell
-and 'a queue_cell = {mutable head : 'a; mutable tail : 'a queue_elem};;
+type 'a queue_elem =
+ | Nil
+ | Cons of 'a queue_cell
+
+and 'a queue_cell = {
+ mutable head : 'a;
+ mutable tail : 'a queue_elem;
+};;
type 'a queue = {
- mutable insert : 'a queue_elem;
- mutable body : 'a queue_elem
+ mutable insert : 'a queue_elem;
+ mutable body : 'a queue_elem;
};;
(* The formatter specific tag handling functions. *)
type formatter_tag_functions = {
- mark_open_tag : tag -> string;
- mark_close_tag : tag -> string;
- print_open_tag : tag -> unit;
- print_close_tag : tag -> unit;
-
+ mark_open_tag : tag -> string;
+ mark_close_tag : tag -> string;
+ print_open_tag : tag -> unit;
+ print_close_tag : tag -> unit;
};;
(* A formatter with all its machinery. *)
type formatter = {
- mutable pp_scan_stack : pp_scan_elem list;
- mutable pp_format_stack : pp_format_elem list;
- mutable pp_tbox_stack : tblock list;
- mutable pp_tag_stack : tag list;
- mutable pp_mark_stack : tag list;
- (* Global variables: default initialization is
- set_margin 78
- set_min_space_left 0. *)
- (* Value of right margin. *)
- mutable pp_margin : int;
- (* Minimal space left before margin, when opening a block. *)
- mutable pp_min_space_left : int;
- (* Maximum value of indentation:
- no blocks can be opened further. *)
- mutable pp_max_indent : int;
- (* Space remaining on the current line. *)
- mutable pp_space_left : int;
- (* Current value of indentation. *)
- mutable pp_current_indent : int;
- (* True when the line has been broken by the pretty-printer. *)
- mutable pp_is_new_line : bool;
- (* Total width of tokens already printed. *)
- mutable pp_left_total : int;
- (* Total width of tokens ever put in queue. *)
- mutable pp_right_total : int;
- (* Current number of opened blocks. *)
- mutable pp_curr_depth : int;
- (* Maximum number of blocks which can be simultaneously opened. *)
- mutable pp_max_boxes : int;
- (* Ellipsis string. *)
- mutable pp_ellipsis : string;
- (* Output function. *)
- mutable pp_output_function : string -> int -> int -> unit;
- (* Flushing function. *)
- mutable pp_flush_function : unit -> unit;
- (* Output of new lines. *)
- mutable pp_output_newline : unit -> unit;
- (* Output of indentation spaces. *)
- mutable pp_output_spaces : int -> unit;
- (* Are tags printed ? *)
- mutable pp_print_tags : bool;
- (* Are tags marked ? *)
- mutable pp_mark_tags : bool;
- (* Find opening and closing markers of tags. *)
- mutable pp_mark_open_tag : tag -> string;
- mutable pp_mark_close_tag : tag -> string;
- mutable pp_print_open_tag : tag -> unit;
- mutable pp_print_close_tag : tag -> unit;
- (* The pretty-printer queue. *)
- mutable pp_queue : pp_queue_elem queue
+ mutable pp_scan_stack : pp_scan_elem list;
+ mutable pp_format_stack : pp_format_elem list;
+ mutable pp_tbox_stack : tblock list;
+ mutable pp_tag_stack : tag list;
+ mutable pp_mark_stack : tag list;
+ (* Global variables: default initialization is
+ set_margin 78
+ set_min_space_left 0. *)
+ (* Value of right margin. *)
+ mutable pp_margin : int;
+ (* Minimal space left before margin, when opening a block. *)
+ mutable pp_min_space_left : int;
+ (* Maximum value of indentation:
+ no blocks can be opened further. *)
+ mutable pp_max_indent : int;
+ (* Space remaining on the current line. *)
+ mutable pp_space_left : int;
+ (* Current value of indentation. *)
+ mutable pp_current_indent : int;
+ (* True when the line has been broken by the pretty-printer. *)
+ mutable pp_is_new_line : bool;
+ (* Total width of tokens already printed. *)
+ mutable pp_left_total : int;
+ (* Total width of tokens ever put in queue. *)
+ mutable pp_right_total : int;
+ (* Current number of opened blocks. *)
+ mutable pp_curr_depth : int;
+ (* Maximum number of blocks which can be simultaneously opened. *)
+ mutable pp_max_boxes : int;
+ (* Ellipsis string. *)
+ mutable pp_ellipsis : string;
+ (* Output function. *)
+ mutable pp_output_function : string -> int -> int -> unit;
+ (* Flushing function. *)
+ mutable pp_flush_function : unit -> unit;
+ (* Output of new lines. *)
+ mutable pp_output_newline : unit -> unit;
+ (* Output of indentation spaces. *)
+ mutable pp_output_spaces : int -> unit;
+ (* Are tags printed ? *)
+ mutable pp_print_tags : bool;
+ (* Are tags marked ? *)
+ mutable pp_mark_tags : bool;
+ (* Find opening and closing markers of tags. *)
+ mutable pp_mark_open_tag : tag -> string;
+ mutable pp_mark_close_tag : tag -> string;
+ mutable pp_print_open_tag : tag -> unit;
+ mutable pp_print_close_tag : tag -> unit;
+ (* The pretty-printer queue. *)
+ mutable pp_queue : pp_queue_elem queue;
};;
(**************************************************************
@@ -161,38 +168,39 @@ type formatter = {
(* Queues auxilliaries. *)
-let make_queue () = {insert = Nil; body = Nil};;
+let make_queue () = { insert = Nil; body = Nil; };;
let clear_queue q = q.insert <- Nil; q.body <- Nil;;
let add_queue x q =
- let c = Cons {head = x; tail = Nil} in
- match q with
- | {insert = Cons cell} -> q.insert <- c; cell.tail <- c
- (* Invariant: when insert is Nil body should be Nil. *)
- | _ -> q.insert <- c; q.body <- c;;
+ let c = Cons { head = x; tail = Nil; } in
+ match q with
+ | { insert = Cons cell } ->
+ q.insert <- c; cell.tail <- c
+ (* Invariant: when insert is Nil body should be Nil. *)
+ | _ -> q.insert <- c; q.body <- c;;
exception Empty_queue;;
let peek_queue = function
- | {body = Cons {head = x}} -> x
- | _ -> raise Empty_queue;;
+ | { body = Cons { head = x; }; } -> x
+ | _ -> raise Empty_queue;;
let take_queue = function
- | {body = Cons {head = x; tail = tl}} as q ->
+ | { body = Cons { head = x; tail = tl; }; } as q ->
q.body <- tl;
if tl = Nil then q.insert <- Nil; (* Maintain the invariant. *)
x
- | _ -> raise Empty_queue;;
+ | _ -> raise Empty_queue;;
(* Enter a token in the pretty-printer queue. *)
let pp_enqueue state ({length = len} as token) =
- state.pp_right_total <- state.pp_right_total + len;
- add_queue token state.pp_queue;;
+ state.pp_right_total <- state.pp_right_total + len;
+ add_queue token state.pp_queue;;
let pp_clear_queue state =
- state.pp_left_total <- 1; state.pp_right_total <- 1;
- clear_queue state.pp_queue;;
+ state.pp_left_total <- 1; state.pp_right_total <- 1;
+ clear_queue state.pp_queue;;
(* Pp_infinity: large value for default tokens size.
@@ -219,47 +227,48 @@ let pp_infinity = 1000000010;;
(* Output functions for the formatter. *)
let pp_output_string state s = state.pp_output_function s 0 (String.length s)
-and pp_output_newline state = state.pp_output_newline ();;
-
-let pp_display_blanks state n = state.pp_output_spaces n;;
+and pp_output_newline state = state.pp_output_newline ()
+and pp_display_blanks state n = state.pp_output_spaces n
+;;
(* To format a break, indenting a new line. *)
let break_new_line state offset width =
- pp_output_newline state;
- state.pp_is_new_line <- true;
- let indent = state.pp_margin - width + offset in
- (* Don't indent more than pp_max_indent. *)
- let real_indent = min state.pp_max_indent indent in
- state.pp_current_indent <- real_indent;
- state.pp_space_left <- state.pp_margin - state.pp_current_indent;
- pp_display_blanks state state.pp_current_indent;;
+ pp_output_newline state;
+ state.pp_is_new_line <- true;
+ let indent = state.pp_margin - width + offset in
+ (* Don't indent more than pp_max_indent. *)
+ let real_indent = min state.pp_max_indent indent in
+ state.pp_current_indent <- real_indent;
+ state.pp_space_left <- state.pp_margin - state.pp_current_indent;
+ pp_display_blanks state state.pp_current_indent;;
(* To force a line break inside a block: no offset is added. *)
let break_line state width = break_new_line state 0 width;;
(* To format a break that fits on the current line. *)
let break_same_line state width =
- state.pp_space_left <- state.pp_space_left - width;
- pp_display_blanks state width;;
+ state.pp_space_left <- state.pp_space_left - width;
+ pp_display_blanks state width;;
(* To indent no more than pp_max_indent, if one tries to open a block
beyond pp_max_indent, then the block is rejected on the left
by simulating a break. *)
let pp_force_break_line state =
- match state.pp_format_stack with
- | Format_elem (bl_ty, width) :: _ ->
- if width > state.pp_space_left then
- (match bl_ty with
- | Pp_fits -> () | Pp_hbox -> () | _ -> break_line state width)
- | _ -> pp_output_newline state;;
+ match state.pp_format_stack with
+ | Format_elem (bl_ty, width) :: _ ->
+ if width > state.pp_space_left then
+ (match bl_ty with
+ | Pp_fits -> () | Pp_hbox -> ()
+ | _ -> break_line state width)
+ | _ -> pp_output_newline state;;
(* To skip a token, if the previous line has been broken. *)
let pp_skip_token state =
- (* When calling pp_skip_token the queue cannot be empty. *)
- match take_queue state.pp_queue with
- {elem_size = size; length = len} ->
- state.pp_left_total <- state.pp_left_total - len;
- state.pp_space_left <- state.pp_space_left + int_of_size size;;
+ (* When calling pp_skip_token the queue cannot be empty. *)
+ match take_queue state.pp_queue with
+ | { elem_size = size; length = len; } ->
+ state.pp_left_total <- state.pp_left_total - len;
+ state.pp_space_left <- state.pp_space_left + int_of_size size;;
(**************************************************************
@@ -271,115 +280,120 @@ let pp_skip_token state =
let format_pp_token state size = function
| Pp_text s ->
- state.pp_space_left <- state.pp_space_left - size;
- pp_output_string state s;
- state.pp_is_new_line <- false
+ state.pp_space_left <- state.pp_space_left - size;
+ pp_output_string state s;
+ state.pp_is_new_line <- false
| Pp_begin (off, ty) ->
- let insertion_point = state.pp_margin - state.pp_space_left in
- if insertion_point > state.pp_max_indent then
- (* can't open a block right there. *)
- begin pp_force_break_line state end;
- let offset = state.pp_space_left - off in
- let bl_type =
- begin match ty with
- | Pp_vbox -> Pp_vbox
- | _ -> if size > state.pp_space_left then ty else Pp_fits
- end in
- state.pp_format_stack <-
- Format_elem (bl_type, offset) :: state.pp_format_stack
+ let insertion_point = state.pp_margin - state.pp_space_left in
+ if insertion_point > state.pp_max_indent then
+ (* can't open a block right there. *)
+ begin pp_force_break_line state end;
+ let offset = state.pp_space_left - off in
+ let bl_type =
+ begin match ty with
+ | Pp_vbox -> Pp_vbox
+ | _ -> if size > state.pp_space_left then ty else Pp_fits
+ end in
+ state.pp_format_stack <-
+ Format_elem (bl_type, offset) :: state.pp_format_stack
| Pp_end ->
- begin match state.pp_format_stack with
- | x :: (y :: l as ls) -> state.pp_format_stack <- ls
- | _ -> () (* No more block to close. *)
- end
+ begin match state.pp_format_stack with
+ | x :: (y :: l as ls) -> state.pp_format_stack <- ls
+ | _ -> () (* No more block to close. *)
+ end
| Pp_tbegin (Pp_tbox _ as tbox) ->
- state.pp_tbox_stack <- tbox :: state.pp_tbox_stack
+ state.pp_tbox_stack <- tbox :: state.pp_tbox_stack
| Pp_tend ->
- begin match state.pp_tbox_stack with
- | x :: ls -> state.pp_tbox_stack <- ls
- | _ -> () (* No more tabulation block to close. *)
- end
+ begin match state.pp_tbox_stack with
+ | x :: ls -> state.pp_tbox_stack <- ls
+ | _ -> () (* No more tabulation block to close. *)
+ end
| Pp_stab ->
- begin match state.pp_tbox_stack with
- | Pp_tbox tabs :: _ ->
- let rec add_tab n = function
- | [] -> [n]
- | x :: l as ls -> if n < x then n :: ls else x :: add_tab n l in
- tabs := add_tab (state.pp_margin - state.pp_space_left) !tabs
- | _ -> () (* No opened tabulation block. *)
- end
+ begin match state.pp_tbox_stack with
+ | Pp_tbox tabs :: _ ->
+ let rec add_tab n = function
+ | [] -> [n]
+ | x :: l as ls -> if n < x then n :: ls else x :: add_tab n l in
+ tabs := add_tab (state.pp_margin - state.pp_space_left) !tabs
+ | _ -> () (* No opened tabulation block. *)
+ end
| Pp_tbreak (n, off) ->
- let insertion_point = state.pp_margin - state.pp_space_left in
- begin match state.pp_tbox_stack with
- | Pp_tbox tabs :: _ ->
- let rec find n = function
- | x :: l -> if x >= n then x else find n l
- | [] -> raise Not_found in
- let tab =
- match !tabs with
- | x :: l ->
- begin try find insertion_point !tabs with Not_found -> x end
- | _ -> insertion_point in
- let offset = tab - insertion_point in
- if offset >= 0 then break_same_line state (offset + n) else
- break_new_line state (tab + off) state.pp_margin
- | _ -> () (* No opened tabulation block. *)
- end
+ let insertion_point = state.pp_margin - state.pp_space_left in
+ begin match state.pp_tbox_stack with
+ | Pp_tbox tabs :: _ ->
+ let rec find n = function
+ | x :: l -> if x >= n then x else find n l
+ | [] -> raise Not_found in
+ let tab =
+ match !tabs with
+ | x :: l ->
+ begin
+ try find insertion_point !tabs with
+ | Not_found -> x
+ end
+ | _ -> insertion_point in
+ let offset = tab - insertion_point in
+ if offset >= 0
+ then break_same_line state (offset + n)
+ else break_new_line state (tab + off) state.pp_margin
+ | _ -> () (* No opened tabulation block. *)
+ end
| Pp_newline ->
- begin match state.pp_format_stack with
- | Format_elem (_, width) :: _ -> break_line state width
- | _ -> pp_output_newline state
- end
+ begin match state.pp_format_stack with
+ | Format_elem (_, width) :: _ -> break_line state width
+ | _ -> pp_output_newline state
+ end
| Pp_if_newline ->
- if state.pp_current_indent != state.pp_margin - state.pp_space_left
- then pp_skip_token state
+ if state.pp_current_indent != state.pp_margin - state.pp_space_left
+ then pp_skip_token state
| Pp_break (n, off) ->
- begin match state.pp_format_stack with
- | Format_elem (ty, width) :: _ ->
- begin match ty with
- | Pp_hovbox ->
- if size > state.pp_space_left
- then break_new_line state off width
- else break_same_line state n
- | Pp_box ->
- (* Have the line just been broken here ? *)
- if state.pp_is_new_line then break_same_line state n else
- if size > state.pp_space_left
- then break_new_line state off width else
- (* break the line here leads to new indentation ? *)
- if state.pp_current_indent > state.pp_margin - width + off
- then break_new_line state off width
- else break_same_line state n
- | Pp_hvbox -> break_new_line state off width
- | Pp_fits -> break_same_line state n
- | Pp_vbox -> break_new_line state off width
- | Pp_hbox -> break_same_line state n
- end
- | _ -> () (* No opened block. *)
- end
+ begin match state.pp_format_stack with
+ | Format_elem (ty, width) :: _ ->
+ begin match ty with
+ | Pp_hovbox ->
+ if size > state.pp_space_left
+ then break_new_line state off width
+ else break_same_line state n
+ | Pp_box ->
+ (* Have the line just been broken here ? *)
+ if state.pp_is_new_line then break_same_line state n else
+ if size > state.pp_space_left
+ then break_new_line state off width else
+ (* break the line here leads to new indentation ? *)
+ if state.pp_current_indent > state.pp_margin - width + off
+ then break_new_line state off width
+ else break_same_line state n
+ | Pp_hvbox -> break_new_line state off width
+ | Pp_fits -> break_same_line state n
+ | Pp_vbox -> break_new_line state off width
+ | Pp_hbox -> break_same_line state n
+ end
+ | _ -> () (* No opened block. *)
+ end
| Pp_open_tag tag_name ->
- let marker = state.pp_mark_open_tag tag_name in
- pp_output_string state marker;
- state.pp_mark_stack <- tag_name :: state.pp_mark_stack
+ let marker = state.pp_mark_open_tag tag_name in
+ pp_output_string state marker;
+ state.pp_mark_stack <- tag_name :: state.pp_mark_stack
| Pp_close_tag ->
- begin match state.pp_mark_stack with
- | tag_name :: tags ->
- let marker = state.pp_mark_close_tag tag_name in
- pp_output_string state marker;
- state.pp_mark_stack <- tags
- | _ -> () (* No more tag to close. *)
- end;;
+ begin match state.pp_mark_stack with
+ | tag_name :: tags ->
+ let marker = state.pp_mark_close_tag tag_name in
+ pp_output_string state marker;
+ state.pp_mark_stack <- tags
+ | _ -> () (* No more tag to close. *)
+ end
+;;
(* Print if token size is known or printing is delayed.
Size is known when not negative.
@@ -407,7 +421,7 @@ let enqueue_advance state tok = pp_enqueue state tok; advance_left state;;
(* To enqueue a string : try to advance. *)
let make_queue_elem size tok len =
- {elem_size = size; token = tok; length = len};;
+ { elem_size = size; token = tok; length = len; };;
let enqueue_string_as state size s =
let len = int_of_size size in
@@ -435,89 +449,99 @@ let clear_scan_stack state = state.pp_scan_stack <- scan_stack_bottom;;
Pattern matching on token in scan stack is also exhaustive,
since scan_push is used on breaks and opening of boxes. *)
let set_size state ty =
- match state.pp_scan_stack with
- | Scan_elem
- (left_tot,
- ({elem_size = size; token = tok} as queue_elem)) :: t ->
- let size = int_of_size size in
- (* test if scan stack contains any data that is not obsolete. *)
- if left_tot < state.pp_left_total then clear_scan_stack state else
- begin match tok with
- | Pp_break (_, _) | Pp_tbreak (_, _) ->
- if ty then
- begin
- queue_elem.elem_size <- size_of_int (state.pp_right_total + size);
- state.pp_scan_stack <- t
- end
- | Pp_begin (_, _) ->
- if not ty then
- begin
- queue_elem.elem_size <- size_of_int (state.pp_right_total + size);
- state.pp_scan_stack <- t
- end
- | _ -> () (* scan_push is only used for breaks and boxes. *)
+ match state.pp_scan_stack with
+ | Scan_elem
+ (left_tot,
+ ({elem_size = size; token = tok} as queue_elem)) :: t ->
+ let size = int_of_size size in
+ (* test if scan stack contains any data that is not obsolete. *)
+ if left_tot < state.pp_left_total then clear_scan_stack state else
+ begin match tok with
+ | Pp_break (_, _) | Pp_tbreak (_, _) ->
+ if ty then
+ begin
+ queue_elem.elem_size <- size_of_int (state.pp_right_total + size);
+ state.pp_scan_stack <- t
+ end
+ | Pp_begin (_, _) ->
+ if not ty then
+ begin
+ queue_elem.elem_size <- size_of_int (state.pp_right_total + size);
+ state.pp_scan_stack <- t
end
- | _ -> () (* scan_stack is never empty. *);;
+ | _ -> () (* scan_push is only used for breaks and boxes. *)
+ end
+ | _ -> () (* scan_stack is never empty. *);;
(* Push a token on scan stack. If b is true set_size is called. *)
let scan_push state b tok =
- pp_enqueue state tok;
- if b then set_size state true;
- state.pp_scan_stack <-
- Scan_elem (state.pp_right_total, tok) :: state.pp_scan_stack;;
+ pp_enqueue state tok;
+ if b then set_size state true;
+ state.pp_scan_stack <-
+ Scan_elem (state.pp_right_total, tok) :: state.pp_scan_stack;;
(* To open a new block :
the user may set the depth bound pp_max_boxes
any text nested deeper is printed as the ellipsis string. *)
let pp_open_box_gen state indent br_ty =
- state.pp_curr_depth <- state.pp_curr_depth + 1;
- if state.pp_curr_depth < state.pp_max_boxes then
- let elem =
- make_queue_elem
- (size_of_int (- state.pp_right_total))
- (Pp_begin (indent, br_ty))
- 0 in
- scan_push state false elem else
- if state.pp_curr_depth = state.pp_max_boxes
- then enqueue_string state state.pp_ellipsis;;
+ state.pp_curr_depth <- state.pp_curr_depth + 1;
+ if state.pp_curr_depth < state.pp_max_boxes then
+ let elem =
+ make_queue_elem
+ (size_of_int (- state.pp_right_total))
+ (Pp_begin (indent, br_ty))
+ 0 in
+ scan_push state false elem else
+ if state.pp_curr_depth = state.pp_max_boxes
+ then enqueue_string state state.pp_ellipsis;;
(* The box which is always opened. *)
let pp_open_sys_box state = pp_open_box_gen state 0 Pp_hovbox;;
(* Close a block, setting sizes of its sub blocks. *)
let pp_close_box state () =
- if state.pp_curr_depth > 1 then
- begin
- if state.pp_curr_depth < state.pp_max_boxes then
- begin
- pp_enqueue state
- {elem_size = size_of_int 0; token = Pp_end; length = 0};
- set_size state true; set_size state false
- end;
- state.pp_curr_depth <- state.pp_curr_depth - 1;
- end;;
+ if state.pp_curr_depth > 1 then
+ begin
+ if state.pp_curr_depth < state.pp_max_boxes then
+ begin
+ pp_enqueue state
+ { elem_size = size_of_int 0; token = Pp_end; length = 0; };
+ set_size state true; set_size state false
+ end;
+ state.pp_curr_depth <- state.pp_curr_depth - 1;
+ end;;
(* Open a tag, pushing it on the tag stack. *)
let pp_open_tag state tag_name =
- if state.pp_print_tags then begin
- state.pp_tag_stack <- tag_name :: state.pp_tag_stack;
- state.pp_print_open_tag tag_name end;
- if state.pp_mark_tags then
- pp_enqueue state
- {elem_size = size_of_int 0; token = Pp_open_tag tag_name; length = 0};;
+ if state.pp_print_tags then
+ begin
+ state.pp_tag_stack <- tag_name :: state.pp_tag_stack;
+ state.pp_print_open_tag tag_name
+ end;
+ if state.pp_mark_tags then
+ pp_enqueue state {
+ elem_size = size_of_int 0;
+ token = Pp_open_tag tag_name;
+ length = 0;
+ }
+;;
(* Close a tag, popping it from the tag stack. *)
let pp_close_tag state () =
- if state.pp_mark_tags then
- pp_enqueue state
- {elem_size = size_of_int 0; token = Pp_close_tag; length = 0};
- if state.pp_print_tags then
- begin match state.pp_tag_stack with
- | tag_name :: tags ->
- state.pp_print_close_tag tag_name;
- state.pp_tag_stack <- tags
- | _ -> () (* No more tag to close. *)
- end;;
+ if state.pp_mark_tags then
+ pp_enqueue state {
+ elem_size = size_of_int 0;
+ token = Pp_close_tag;
+ length = 0;
+ };
+ if state.pp_print_tags then
+ begin
+ match state.pp_tag_stack with
+ | tag_name :: tags ->
+ state.pp_print_close_tag tag_name;
+ state.pp_tag_stack <- tags
+ | _ -> () (* No more tag to close. *)
+ end;;
let pp_set_print_tags state b = state.pp_print_tags <- b;;
let pp_set_mark_tags state b = state.pp_mark_tags <- b;;
@@ -526,10 +550,10 @@ let pp_get_mark_tags state () = state.pp_mark_tags;;
let pp_set_tags state b = pp_set_print_tags state b; pp_set_mark_tags state b;;
let pp_get_formatter_tag_functions state () = {
- mark_open_tag = state.pp_mark_open_tag;
- mark_close_tag = state.pp_mark_close_tag;
- print_open_tag = state.pp_print_open_tag;
- print_close_tag = state.pp_print_close_tag;
+ mark_open_tag = state.pp_mark_open_tag;
+ mark_close_tag = state.pp_mark_close_tag;
+ print_open_tag = state.pp_print_open_tag;
+ print_close_tag = state.pp_print_close_tag;
};;
let pp_set_formatter_tag_functions state {
@@ -545,26 +569,26 @@ let pp_set_formatter_tag_functions state {
(* Initialize pretty-printer. *)
let pp_rinit state =
- pp_clear_queue state;
- clear_scan_stack state;
- state.pp_format_stack <- [];
- state.pp_tbox_stack <- [];
- state.pp_tag_stack <- [];
- state.pp_mark_stack <- [];
- state.pp_current_indent <- 0;
- state.pp_curr_depth <- 0;
- state.pp_space_left <- state.pp_margin;
- pp_open_sys_box state;;
+ pp_clear_queue state;
+ clear_scan_stack state;
+ state.pp_format_stack <- [];
+ state.pp_tbox_stack <- [];
+ state.pp_tag_stack <- [];
+ state.pp_mark_stack <- [];
+ state.pp_current_indent <- 0;
+ state.pp_curr_depth <- 0;
+ state.pp_space_left <- state.pp_margin;
+ pp_open_sys_box state;;
(* Flushing pretty-printer queue. *)
let pp_flush_queue state b =
- while state.pp_curr_depth > 1 do
- pp_close_box state ()
- done;
- state.pp_right_total <- pp_infinity;
- advance_left state;
- if b then pp_output_newline state;
- pp_rinit state;;
+ while state.pp_curr_depth > 1 do
+ pp_close_box state ()
+ done;
+ state.pp_right_total <- pp_infinity;
+ advance_left state;
+ if b then pp_output_newline state;
+ pp_rinit state;;
(**************************************************************
@@ -609,9 +633,9 @@ and pp_open_box state indent = pp_open_box_gen state indent Pp_box;;
(* Print a new line after printing all queued text
(same for print_flush but without a newline). *)
let pp_print_newline state () =
- pp_flush_queue state true; state.pp_flush_function ()
+ pp_flush_queue state true; state.pp_flush_function ()
and pp_print_flush state () =
- pp_flush_queue state false; state.pp_flush_function ();;
+ pp_flush_queue state false; state.pp_flush_function ();;
(* To get a newline when one does not want to close the current block. *)
let pp_force_newline state () =
@@ -649,11 +673,13 @@ let pp_open_tbox state () =
(* Close a tabulation block. *)
let pp_close_tbox state () =
- if state.pp_curr_depth > 1 then begin
+ if state.pp_curr_depth > 1 then
+ begin
if state.pp_curr_depth < state.pp_max_boxes then
let elem = make_queue_elem (size_of_int 0) Pp_tend 0 in
enqueue_advance state elem;
- state.pp_curr_depth <- state.pp_curr_depth - 1 end;;
+ state.pp_curr_depth <- state.pp_curr_depth - 1
+ end;;
(* Print a tabulation break. *)
let pp_print_tbreak state width offset =
@@ -714,15 +740,15 @@ let pp_set_margin state n =
let n = pp_limit n in
state.pp_margin <- n;
let new_max_indent =
- (* Try to maintain max_indent to its actual value. *)
- if state.pp_max_indent <= state.pp_margin
- then state.pp_max_indent else
- (* If possible maintain pp_min_space_left to its actual value,
- if this leads to a too small max_indent, take half of the
- new margin, if it is greater than 1. *)
- max (max (state.pp_margin - state.pp_min_space_left)
- (state.pp_margin / 2)) 1 in
- (* Rebuild invariants. *)
+ (* Try to maintain max_indent to its actual value. *)
+ if state.pp_max_indent <= state.pp_margin
+ then state.pp_max_indent else
+ (* If possible maintain pp_min_space_left to its actual value,
+ if this leads to a too small max_indent, take half of the
+ new margin, if it is greater than 1. *)
+ max (max (state.pp_margin - state.pp_min_space_left)
+ (state.pp_margin / 2)) 1 in
+ (* Rebuild invariants. *)
pp_set_max_indent state new_max_indent;;
let pp_get_margin state () = state.pp_margin;;
@@ -758,51 +784,51 @@ let default_pp_print_open_tag s = ();;
let default_pp_print_close_tag = default_pp_print_open_tag;;
let pp_make_formatter f g h i =
- (* The initial state of the formatter contains a dummy box. *)
- let pp_q = make_queue () in
- let sys_tok =
- make_queue_elem (size_of_int (-1)) (Pp_begin (0, Pp_hovbox)) 0 in
- add_queue sys_tok pp_q;
- let sys_scan_stack =
- (Scan_elem (1, sys_tok)) :: scan_stack_bottom in
- {pp_scan_stack = sys_scan_stack;
- pp_format_stack = [];
- pp_tbox_stack = [];
- pp_tag_stack = [];
- pp_mark_stack = [];
- pp_margin = 78;
- pp_min_space_left = 10;
- pp_max_indent = 78 - 10;
- pp_space_left = 78;
- pp_current_indent = 0;
- pp_is_new_line = true;
- pp_left_total = 1;
- pp_right_total = 1;
- pp_curr_depth = 1;
- pp_max_boxes = max_int;
- pp_ellipsis = ".";
- pp_output_function = f;
- pp_flush_function = g;
- pp_output_newline = h;
- pp_output_spaces = i;
- pp_print_tags = false;
- pp_mark_tags = false;
- pp_mark_open_tag = default_pp_mark_open_tag;
- pp_mark_close_tag = default_pp_mark_close_tag;
- pp_print_open_tag = default_pp_print_open_tag;
- pp_print_close_tag = default_pp_print_close_tag;
- pp_queue = pp_q
- };;
+ (* The initial state of the formatter contains a dummy box. *)
+ let pp_q = make_queue () in
+ let sys_tok =
+ make_queue_elem (size_of_int (-1)) (Pp_begin (0, Pp_hovbox)) 0 in
+ add_queue sys_tok pp_q;
+ let sys_scan_stack =
+ (Scan_elem (1, sys_tok)) :: scan_stack_bottom in
+ {pp_scan_stack = sys_scan_stack;
+ pp_format_stack = [];
+ pp_tbox_stack = [];
+ pp_tag_stack = [];
+ pp_mark_stack = [];
+ pp_margin = 78;
+ pp_min_space_left = 10;
+ pp_max_indent = 78 - 10;
+ pp_space_left = 78;
+ pp_current_indent = 0;
+ pp_is_new_line = true;
+ pp_left_total = 1;
+ pp_right_total = 1;
+ pp_curr_depth = 1;
+ pp_max_boxes = max_int;
+ pp_ellipsis = ".";
+ pp_output_function = f;
+ pp_flush_function = g;
+ pp_output_newline = h;
+ pp_output_spaces = i;
+ pp_print_tags = false;
+ pp_mark_tags = false;
+ pp_mark_open_tag = default_pp_mark_open_tag;
+ pp_mark_close_tag = default_pp_mark_close_tag;
+ pp_print_open_tag = default_pp_print_open_tag;
+ pp_print_close_tag = default_pp_print_close_tag;
+ pp_queue = pp_q;
+ };;
(* Default function to output spaces. *)
let blank_line = String.make 80 ' ';;
let rec display_blanks state n =
- if n > 0 then
- if n <= 80 then state.pp_output_function blank_line 0 n else
- begin
- state.pp_output_function blank_line 0 80;
- display_blanks state (n - 80)
- end;;
+ if n > 0 then
+ if n <= 80 then state.pp_output_function blank_line 0 n else
+ begin
+ state.pp_output_function blank_line 0 80;
+ display_blanks state (n - 80)
+ end;;
(* Default function to output new lines. *)
let display_newline state () = state.pp_output_function "\n" 0 1;;
@@ -823,9 +849,9 @@ let formatter_of_buffer b =
let stdbuf = Buffer.create 512;;
(* Predefined formatters. *)
-let str_formatter = formatter_of_buffer stdbuf;;
-let std_formatter = formatter_of_out_channel stdout;;
-let err_formatter = formatter_of_out_channel stderr;;
+let str_formatter = formatter_of_buffer stdbuf
+and std_formatter = formatter_of_out_channel stdout
+and err_formatter = formatter_of_out_channel stderr;;
let flush_str_formatter () =
pp_flush_queue str_formatter false;
@@ -882,32 +908,32 @@ and set_ellipsis_text = pp_set_ellipsis_text std_formatter
and get_ellipsis_text = pp_get_ellipsis_text std_formatter
and set_formatter_out_channel =
- pp_set_formatter_out_channel std_formatter
+ pp_set_formatter_out_channel std_formatter
and set_formatter_output_functions =
- pp_set_formatter_output_functions std_formatter
+ pp_set_formatter_output_functions std_formatter
and get_formatter_output_functions =
- pp_get_formatter_output_functions std_formatter
+ pp_get_formatter_output_functions std_formatter
and set_all_formatter_output_functions =
- pp_set_all_formatter_output_functions std_formatter
+ pp_set_all_formatter_output_functions std_formatter
and get_all_formatter_output_functions =
- pp_get_all_formatter_output_functions std_formatter
+ pp_get_all_formatter_output_functions std_formatter
and set_formatter_tag_functions =
- pp_set_formatter_tag_functions std_formatter
+ pp_set_formatter_tag_functions std_formatter
and get_formatter_tag_functions =
- pp_get_formatter_tag_functions std_formatter
+ pp_get_formatter_tag_functions std_formatter
and set_print_tags =
- pp_set_print_tags std_formatter
+ pp_set_print_tags std_formatter
and get_print_tags =
- pp_get_print_tags std_formatter
+ pp_get_print_tags std_formatter
and set_mark_tags =
- pp_set_mark_tags std_formatter
+ pp_set_mark_tags std_formatter
and get_mark_tags =
- pp_get_mark_tags std_formatter
+ pp_get_mark_tags std_formatter
and set_tags =
- pp_set_tags std_formatter
+ pp_set_tags std_formatter
;;
@@ -949,24 +975,24 @@ let format_int_of_string fmt i s =
(* Getting strings out of buffers. *)
let get_buffer_out b =
- let s = Buffer.contents b in
- Buffer.reset b;
- s;;
+ let s = Buffer.contents b in
+ Buffer.reset b;
+ s;;
(* [ppf] is supposed to be a pretty-printer that outputs in buffer [b]:
to extract 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;;
+ 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;;
+ 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
@@ -986,73 +1012,74 @@ let implode_rev s0 = function
let mkprintf to_s get_out =
let rec kprintf k fmt =
+
let len = Sformat.length fmt in
let kpr fmt v =
let ppf = get_out fmt in
let print_as = ref None in
let pp_print_as_char c =
- match !print_as with
- | None -> pp_print_char ppf c
- | Some size ->
- pp_print_as_size ppf size (String.make 1 c);
- print_as := None
+ match !print_as with
+ | None -> pp_print_char ppf c
+ | Some size ->
+ pp_print_as_size ppf size (String.make 1 c);
+ print_as := None
and pp_print_as_string s =
- match !print_as with
- | None -> pp_print_string ppf s
- | Some size ->
- pp_print_as_size ppf size s;
- print_as := None in
+ match !print_as with
+ | None -> pp_print_string ppf s
+ | Some size ->
+ pp_print_as_size ppf size s;
+ print_as := None in
let rec doprn n i =
if i >= len then Obj.magic (k ppf) else
match Sformat.get fmt i with
| '%' ->
- Tformat.scan_format fmt v n i cont_s cont_a cont_t cont_f cont_m
+ 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 ppf n (succ i)
- | ']' ->
- pp_close_box ppf ();
- doprn n (succ i)
- | '{' ->
- do_pp_open_tag ppf n (succ i)
- | '}' ->
- pp_close_tag ppf ();
- doprn n (succ i)
- | ' ' ->
- pp_print_space ppf ();
- doprn n (succ i)
- | ',' ->
- pp_print_cut ppf ();
- doprn n (succ i)
- | '?' ->
- pp_print_flush ppf ();
- doprn n (succ i)
- | '.' ->
- pp_print_newline ppf ();
- doprn n (succ i)
- | '\n' ->
- pp_force_newline ppf ();
- doprn n (succ i)
- | ';' ->
- do_pp_break ppf 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
- | '@' as c ->
- pp_print_as_char c;
- doprn n (succ i)
- | c -> invalid_format fmt i
- end
+ 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 ppf n (succ i)
+ | ']' ->
+ pp_close_box ppf ();
+ doprn n (succ i)
+ | '{' ->
+ do_pp_open_tag ppf n (succ i)
+ | '}' ->
+ pp_close_tag ppf ();
+ doprn n (succ i)
+ | ' ' ->
+ pp_print_space ppf ();
+ doprn n (succ i)
+ | ',' ->
+ pp_print_cut ppf ();
+ doprn n (succ i)
+ | '?' ->
+ pp_print_flush ppf ();
+ doprn n (succ i)
+ | '.' ->
+ pp_print_newline ppf ();
+ doprn n (succ i)
+ | '\n' ->
+ pp_force_newline ppf ();
+ doprn n (succ i)
+ | ';' ->
+ do_pp_break ppf 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
+ | '@' as c ->
+ pp_print_as_char c;
+ doprn n (succ i)
+ | c -> invalid_format fmt i
+ end
| c ->
- pp_print_as_char c;
- doprn n (succ i)
+ pp_print_as_char c;
+ doprn n (succ i)
and cont_s n s i =
pp_print_as_string s; doprn n i
@@ -1074,129 +1101,131 @@ let mkprintf to_s get_out =
kprintf (Obj.magic (fun _ -> doprn n i)) sfmt
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
- | '%' ->
+ 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
+ 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
+ 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
+ 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' ->
+ 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
- | c -> Pp_hbox, i
- end
- | 'b' -> Pp_box, succ i
- | 'v' -> Pp_vbox, succ i
- | _ -> Pp_box, i
+ format_invalid_arg
+ ("bad box name ho" ^ String.make 1 c) fmt i
+ end
+ | 'v' -> Pp_hvbox, succ i
+ | c -> 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
- | c -> get accu n i (succ j) in
- get [] n i i
+ 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
+ | c -> 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
- | '<' ->
+ 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
+ | 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
- | '<' ->
+ 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
+ | 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
- | '<' ->
+ 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
+ | c -> pp_open_tag ppf ""; doprn n i in
doprn (Sformat.index_of_int 0) 0 in
- Tformat.kapr kpr fmt in
+ Tformat.kapr kpr fmt in
kprintf;;
diff --git a/stdlib/int32.mli b/stdlib/int32.mli
index dc733ec9f..eeafb1a2f 100644
--- a/stdlib/int32.mli
+++ b/stdlib/int32.mli
@@ -160,9 +160,5 @@ val compare: t -> t -> int
(** {6 Deprecated functions} *)
external format : string -> int32 -> string = "caml_int32_format"
-(** [Int32.format fmt n] return the string representation of the
- 32-bit integer [n] in the format specified by [fmt].
- [fmt] is a [Printf]-style format consisting of exactly
- one [%d], [%i], [%u], [%x], [%X] or [%o] conversion specification.
- This function is deprecated; use {!Printf.sprintf} with a [%lx] format
- instead. *)
+(** Do not use this deprecated function. Instead,
+ used {!Printf.sprintf} with a [%l...] format. *)
diff --git a/stdlib/int64.mli b/stdlib/int64.mli
index 7bc39e612..3b641338e 100644
--- a/stdlib/int64.mli
+++ b/stdlib/int64.mli
@@ -182,9 +182,5 @@ val compare: t -> t -> int
(** {6 Deprecated functions} *)
external format : string -> int64 -> string = "caml_int64_format"
-(** [Int64.format fmt n] return the string representation of the
- 64-bit integer [n] in the format specified by [fmt].
- [fmt] is a {!Printf}-style format consisting of exactly one
- [%d], [%i], [%u], [%x], [%X] or [%o] conversion specification.
- This function is deprecated; use {!Printf.sprintf} with a [%Lx] format
- instead. *)
+(** Do not use this deprecated function. Instead,
+ used {!Printf.sprintf} with a [%L...] format. *)
diff --git a/stdlib/printf.mli b/stdlib/printf.mli
index e8bd7d6c9..6bd692d0b 100644
--- a/stdlib/printf.mli
+++ b/stdlib/printf.mli
@@ -27,7 +27,7 @@ val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a
Conversion specifications have the following form:
- [% \[positional specifier\] \[flags\] \[width\] \[.precision\] type]
+ [% \[flags\] \[width\] \[.precision\] type]
In short, a conversion specification consists in the [%] character,
followed by optional modifiers and a type which is made of one or
@@ -79,10 +79,6 @@ val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a
- [!]: take no argument and flush the output.
- [%]: take no argument and output one [%] character.
- The optional [positional specifier] consists of an integer followed
- by a [$]; the integer indicates which argument to use, the first
- argument being denoted by 1.
-
The optional [flags] are:
- [-]: left-justify the output (default is right justification).
- [0]: for numerical conversions, pad with zeroes instead of spaces.
@@ -102,10 +98,9 @@ val fprintf : out_channel -> ('a, out_channel, unit) format -> 'a
The integer in a [width] or [precision] can also be specified as
[*], in which case an extra integer argument is taken to specify
the corresponding [width] or [precision]. This integer argument
- precedes immediately the argument to print, unless an optional
- [positional specifier] is given to indicates which argument to
- use. For instance, [%.*3$f] prints a [float] with as many fractional
- digits as the value of the third argument. *)
+ precedes immediately the argument to print.
+ For instance, [%.*f] prints a [float] with as many fractional
+ digits as the value of the argument given before the float. *)
val printf : ('a, out_channel, unit) format -> 'a
(** Same as {!Printf.fprintf}, but output on [stdout]. *)
diff --git a/test/Moretest/recmod.ml b/test/Moretest/recmod.ml
index 1573ef01b..e4c6751c5 100644
--- a/test/Moretest/recmod.ml
+++ b/test/Moretest/recmod.ml
@@ -62,13 +62,6 @@ let _ =
(* Early application *)
-(*
-module rec Bad
- : sig val f : int -> int end
- = struct let f = let y = Bad.f 5 in fun x -> x+y end
-;;
-*)
-
let _ =
let res =
try
@@ -84,6 +77,8 @@ let _ =
test 30 res true
;;
+(* Early strict evaluation *)
+
(*
module rec Cyclic
: sig val x : int end
@@ -156,6 +151,24 @@ module rec PolyRec
end
;;
+(* Wrong LHS signatures (PR#4336) *)
+
+(*
+module type ASig = sig type a val a:a val print:a -> unit end
+module type BSig = sig type b val b:b val print:b -> unit end
+
+module A = struct type a = int let a = 0 let print = print_int end
+module B = struct type b = float let b = 0.0 let print = print_float end
+
+module MakeA (Empty:sig end) : ASig = A
+module MakeB (Empty:sig end) : BSig = B
+
+module
+ rec NewA : ASig = MakeA (struct end)
+ and NewB : BSig with type b = NewA.a = MakeB (struct end);;
+
+*)
+
(* Expressions and bindings *)
module StringSet = Set.Make(String);;
@@ -458,6 +471,124 @@ let _ =
test 100 (F.f (F.X 1)) false;
test 101 (F.f (F.Y 2)) true
+(* PR#4316 *)
+module G(S : sig val x : int Lazy.t end) = struct include S end
+
+module M1 = struct let x = lazy 3 end
+
+let _ = Lazy.force M1.x
+
+module rec M2 : sig val x : int Lazy.t end = G(M1)
+
+let _ =
+ test 102 (Lazy.force M2.x) 3
+
+let _ = Gc.full_major() (* will shortcut forwarding in M1.x *)
+
+module rec M3 : sig val x : int Lazy.t end = G(M1)
+
+let _ =
+ test 103 (Lazy.force M3.x) 3
+
+(* PR#4450 *)
+
+module PR_4450_1 = struct
+ module type MyT = sig type 'a t = Succ of 'a t end
+ module MyMap(X : MyT) = X
+ module rec MyList : MyT = MyMap(MyList)
+end;;
+
+module PR_4450_2 = struct
+ module type MyT = sig
+ type 'a wrap = My of 'a t
+ and 'a t = private < map : 'b. ('a -> 'b) ->'b wrap; .. >
+ val create : 'a list -> 'a t
+ end
+ module MyMap(X : MyT) = struct
+ include X
+ class ['a] c l = object (self)
+ method map : 'b. ('a -> 'b) -> 'b wrap =
+ fun f -> My (create (List.map f l))
+ end
+ end
+ module rec MyList : sig
+ type 'a wrap = My of 'a t
+ and 'a t = < map : 'b. ('a -> 'b) ->'b wrap >
+ val create : 'a list -> 'a t
+ end = struct
+ include MyMap(MyList)
+ let create l = new c l
+ end
+end;;
+
+(* A synthetic example of bootstrapped data structure
+ (suggested by J-C Filliatre) *)
+
+module type ORD = sig
+ type t
+ val compare : t -> t -> int
+end
+
+module type SET = sig
+ type elt
+ type t
+ val iter : (elt -> unit) -> t -> unit
+end
+
+type 'a tree = E | N of 'a tree * 'a * 'a tree
+
+module Bootstrap2
+ (MakeDiet : functor (X: ORD) -> SET with type t = X.t tree and type elt = X.t)
+ : SET with type elt = int =
+struct
+
+ type elt = int
+
+ module rec Elt : sig
+ type t = I of int * int | D of int * Diet.t * int
+ val compare : t -> t -> int
+ val iter : (int -> unit) -> t -> unit
+ end =
+ struct
+ type t = I of int * int | D of int * Diet.t * int
+ let compare x1 x2 = 0
+ let rec iter f = function
+ | I (l, r) -> for i = l to r do f i done
+ | D (_, d, _) -> Diet.iter (iter f) d
+ end
+
+ and Diet : SET with type t = Elt.t tree and type elt = Elt.t = MakeDiet(Elt)
+
+ type t = Diet.t
+ let iter f = Diet.iter (Elt.iter f)
+end
+
+(* PR 4470: simplified from OMake's sources *)
+
+module rec DirElt
+ : sig
+ type t = DirRoot | DirSub of DirHash.t
+ end
+ = struct
+ type t = DirRoot | DirSub of DirHash.t
+ end
+
+and DirCompare
+ : sig
+ type t = DirElt.t
+ end
+ = struct
+ type t = DirElt.t
+ end
+
+and DirHash
+ : sig
+ type t = DirElt.t list
+ end
+ = struct
+ type t = DirCompare.t list
+ end
+
(** Ill-formed type abbreviations. *)
(**
diff --git a/testlabl/bugs/pr4435.ml b/testlabl/bugs/pr4435.ml
new file mode 100644
index 000000000..c9e1d4997
--- /dev/null
+++ b/testlabl/bugs/pr4435.ml
@@ -0,0 +1,11 @@
+(* Two v's in the same class *)
+class c v = object initializer print_endline v val v = 42 end;;
+new c "42";;
+
+(* Two hidden v's in the same class! *)
+class c (v : int) =
+ object
+ method v0 = v
+ inherit ((fun v -> object method v : string = v end) "42")
+ end;;
+(new c 42)#v0;;
diff --git a/tools/depend.ml b/tools/depend.ml
index c39002516..a89508502 100644
--- a/tools/depend.ml
+++ b/tools/depend.ml
@@ -268,8 +268,8 @@ and add_class_expr bv ce =
add bv l; List.iter (add_type bv) tyl
| Pcl_structure(pat, fieldl) ->
add_pattern bv pat; List.iter (add_class_field bv) fieldl
- | Pcl_fun(_, _, pat, ce) ->
- add_pattern bv pat; add_class_expr bv ce
+ | Pcl_fun(_, opte, pat, ce) ->
+ add_opt add_expr bv opte; add_pattern bv pat; add_class_expr bv ce
| Pcl_apply(ce, exprl) ->
add_class_expr bv ce; List.iter (fun (_,e) -> add_expr bv e) exprl
| Pcl_let(_, pel, ce) ->
diff --git a/tools/make-package-macosx b/tools/make-package-macosx
index 1e483685b..39e3908e0 100755
--- a/tools/make-package-macosx
+++ b/tools/make-package-macosx
@@ -18,8 +18,8 @@ cd package-macosx
rm -rf ocaml.pkg ocaml-rw.dmg
VERSION=`head -1 ../VERSION`
-VERSION_MAJOR=`sed -n -e '1s/^\([0-9]*\)\..*/\1/p' ../VERSION
-VERSION_MINOR=`sed -n -e '1s/^[0-9]*\.\([0-9]*\)[.+].*/\1/p' ../VERSION
+VERSION_MAJOR=`sed -n -e '1s/^\([0-9]*\)\..*/\1/p' ../VERSION`
+VERSION_MINOR=`sed -n -e '1s/^[0-9]*\.\([0-9]*\)[.+].*/\1/p' ../VERSION`
cat >Description.plist <<EOF
<?xml version="1.0" encoding="UTF-8"?>
@@ -86,8 +86,8 @@ mkdir -p resources
# stop here -> |
cat >resources/ReadMe.txt <<EOF
This package installs Objective Caml version ${VERSION}.
-You need Mac OS X 10.4.x (Tiger), with the
-XCode tools (v2.4) installed (and optionally X11).
+You need Mac OS X 10.5.x (Jaguar), with the
+XCode tools (v3.x) installed (and optionally X11).
Files will be installed in the following directories:
diff --git a/typing/btype.ml b/typing/btype.ml
index 290d43e58..84f21f791 100644
--- a/typing/btype.ml
+++ b/typing/btype.ml
@@ -176,8 +176,7 @@ let rec iter_row f row =
match (repr row.row_more).desc with
Tvariant row -> iter_row f row
| Tvar | Tunivar | Tsubst _ | Tconstr _ ->
- Misc.may (fun (_,l) -> List.iter f l) row.row_name;
- List.iter f row.row_bound
+ Misc.may (fun (_,l) -> List.iter f l) row.row_name
| _ -> assert false
let iter_type_expr f ty =
@@ -203,7 +202,6 @@ let rec iter_abbrev f = function
| Mlink rem -> iter_abbrev f !rem
let copy_row f fixed row keep more =
- let bound = ref [] in
let fields = List.map
(fun (l, fi) -> l,
match row_field_repr fi with
@@ -212,10 +210,6 @@ let copy_row f fixed row keep more =
let e = if keep then e else ref None in
let m = if row.row_fixed then fixed else m in
let tl = List.map f tl in
- bound := List.filter
- (function {desc=Tconstr(_,[],_)} -> false | _ -> true)
- (List.map repr tl)
- @ !bound;
Reither(c, tl, m, e)
| _ -> fi)
row.row_fields in
@@ -223,7 +217,7 @@ let copy_row f fixed row keep more =
match row.row_name with None -> None
| Some (path, tl) -> Some (path, List.map f tl) in
{ row_fields = fields; row_more = more;
- row_bound = !bound; row_fixed = row.row_fixed && fixed;
+ row_bound = (); row_fixed = row.row_fixed && fixed;
row_closed = row.row_closed; row_name = name; }
let rec copy_kind = function
diff --git a/typing/ctype.ml b/typing/ctype.ml
index 8451598ce..9f4ed9048 100644
--- a/typing/ctype.ml
+++ b/typing/ctype.ml
@@ -322,17 +322,21 @@ let rec class_type_arity =
let sort_row_fields = Sort.list (fun (p,_) (q,_) -> p < q)
+let rec merge_rf r1 r2 pairs fi1 fi2 =
+ match fi1, fi2 with
+ (l1,f1 as p1)::fi1', (l2,f2 as p2)::fi2' ->
+ if l1 = l2 then merge_rf r1 r2 ((l1,f1,f2)::pairs) fi1' fi2' else
+ if l1 < l2 then merge_rf (p1::r1) r2 pairs fi1' fi2 else
+ merge_rf r1 (p2::r2) pairs fi1 fi2'
+ | [], _ -> (List.rev r1, List.rev_append r2 fi2, pairs)
+ | _, [] -> (List.rev_append r1 fi1, List.rev r2, pairs)
+
let merge_row_fields fi1 fi2 =
- let rec merge r1 r2 pairs fi1 fi2 =
- match fi1, fi2 with
- (l1,f1 as p1)::fi1', (l2,f2 as p2)::fi2' ->
- if l1 = l2 then merge r1 r2 ((l1,f1,f2)::pairs) fi1' fi2' else
- if l1 < l2 then merge (p1::r1) r2 pairs fi1' fi2 else
- merge r1 (p2::r2) pairs fi1 fi2'
- | [], _ -> (List.rev r1, List.rev_append r2 fi2, pairs)
- | _, [] -> (List.rev_append r1 fi1, List.rev r2, pairs)
- in
- merge [] [] [] (sort_row_fields fi1) (sort_row_fields fi2)
+ match fi1, fi2 with
+ [], _ | _, [] -> (fi1, fi2, [])
+ | [p1], _ when not (List.mem_assoc (fst p1) fi2) -> (fi1, fi2, [])
+ | _, [p2] when not (List.mem_assoc (fst p2) fi1) -> (fi1, fi2, [])
+ | _ -> merge_rf [] [] [] (sort_row_fields fi1) (sort_row_fields fi2)
let rec filter_row_fields erase = function
[] -> []
@@ -364,7 +368,7 @@ let rec closed_schema_rec ty =
closed_schema_rec t2
| Tvariant row ->
let row = row_repr row in
- iter_row closed_schema_rec {row with row_bound = []};
+ iter_row closed_schema_rec row;
if not (static_row row) then closed_schema_rec row.row_more
| _ ->
iter_type_expr closed_schema_rec ty
@@ -401,7 +405,7 @@ let rec free_vars_rec real ty =
free_vars_rec true ty1; free_vars_rec false ty2
| Tvariant row ->
let row = row_repr row in
- iter_row (free_vars_rec true) {row with row_bound = []};
+ iter_row (free_vars_rec true) row;
if not (static_row row) then free_vars_rec false row.row_more
| _ ->
iter_type_expr (free_vars_rec true) ty
@@ -1460,7 +1464,7 @@ let mkvariant fields closed =
newgenty
(Tvariant
{row_fields = fields; row_closed = closed; row_more = newvar();
- row_bound = []; row_fixed = false; row_name = None })
+ row_bound = (); row_fixed = false; row_name = None })
(**** Unification ****)
@@ -1764,8 +1768,7 @@ and unify_row env row1 row2 =
then row2.row_name
else None
in
- let bound = row1.row_bound @ row2.row_bound in
- let row0 = {row_fields = []; row_more = more; row_bound = bound;
+ let row0 = {row_fields = []; row_more = more; row_bound = ();
row_closed = closed; row_fixed = fixed; row_name = name} in
let set_more row rest =
let rest =
@@ -2827,7 +2830,6 @@ let rec build_subtype env visited loops posi level t =
let level' = pred_enlarge level in
let visited =
t :: if level' < level then [] else filter_visited visited in
- let bound = ref row.row_bound in
let fields = filter_row_fields false row.row_fields in
let fields =
List.map
@@ -2839,18 +2841,18 @@ let rec build_subtype env visited loops posi level t =
orig, Unchanged
| Rpresent(Some t) ->
let (t', c) = build_subtype env visited loops posi level' t in
- if posi && level > 0 then begin
- bound := t' :: !bound;
- (l, Reither(false, [t'], false, ref None)), c
- end else
- (l, Rpresent(Some t')), c
+ let f =
+ if posi && level > 0
+ then Reither(false, [t'], false, ref None)
+ else Rpresent(Some t')
+ in (l, f), c
| _ -> assert false)
fields
in
let c = collect fields in
let row =
{ row_fields = List.map fst fields; row_more = newvar();
- row_bound = !bound; row_closed = posi; row_fixed = false;
+ row_bound = (); row_closed = posi; row_fixed = false;
row_name = if c > Unchanged then None else row.row_name }
in
(newty (Tvariant row), Changed)
@@ -3174,13 +3176,9 @@ let rec normalize_type_rec env ty =
row.row_fields in
let fields =
List.sort (fun (p,_) (q,_) -> compare p q)
- (List.filter (fun (_,fi) -> fi <> Rabsent) fields)
- and bound = List.fold_left
- (fun tyl ty -> if List.memq ty tyl then tyl else ty :: tyl)
- [] (List.map repr row.row_bound)
- in
+ (List.filter (fun (_,fi) -> fi <> Rabsent) fields) in
log_type ty;
- ty.desc <- Tvariant {row with row_fields = fields; row_bound = bound}
+ ty.desc <- Tvariant {row with row_fields = fields}
| Tobject (fi, nm) ->
begin match !nm with
| None -> ()
diff --git a/typing/includemod.ml b/typing/includemod.ml
index 3f75546ea..610025e5d 100644
--- a/typing/includemod.ml
+++ b/typing/includemod.ml
@@ -208,8 +208,9 @@ and signatures env subst sig1 sig2 =
| item2 :: rem ->
let (id2, name2) = item_ident_name item2 in
let name2, report =
- match name2 with
- Field_type s when let l = String.length s in
+ match item2, name2 with
+ Tsig_type (_, {type_manifest=None}, _), Field_type s
+ when let l = String.length s in
l >= 4 && String.sub s (l-4) 4 = "#row" ->
(* Do not report in case of failure,
as the main type will generate an error *)
diff --git a/typing/oprint.ml b/typing/oprint.ml
index 139daadc2..819489750 100644
--- a/typing/oprint.ml
+++ b/typing/oprint.ml
@@ -75,7 +75,7 @@ let print_out_value ppf tree =
fprintf ppf "@[<1>%a@ (%a)@]" print_ident name
(print_tree_list print_tree_1 ",") params
| Oval_variant (name, Some param) ->
- fprintf ppf "@[<2>`%s@ %a@]" name print_simple_tree param
+ fprintf ppf "@[<2>`%s@ %a@]" name print_constr_param param
| tree -> print_simple_tree ppf tree
and print_constr_param ppf = function
| Oval_int i -> parenthesize_if_neg ppf "%i" i (i < 0)
diff --git a/typing/parmatch.ml b/typing/parmatch.ml
index 3624fcc79..b9673a075 100644
--- a/typing/parmatch.ml
+++ b/typing/parmatch.ml
@@ -45,7 +45,7 @@ let zero = make_pat (Tpat_constant (Const_int 0)) Ctype.none Env.empty
(* p and q compatible means, there exists V that matches both *)
-let is_absent tag row = Btype.row_field tag row = Rabsent
+let is_absent tag row = Btype.row_field tag !row = Rabsent
let is_absent_pat p = match p.pat_desc with
| Tpat_variant (tag, _, row) -> is_absent tag row
@@ -585,24 +585,29 @@ let close_variant env row =
row_closed = true; row_name = nm}))
end
+let row_of_pat pat =
+ match Ctype.expand_head pat.pat_env pat.pat_type with
+ {desc = Tvariant row} -> Btype.row_repr row
+ | _ -> assert false
+
(*
Check whether the first column of env makes up a complete signature or
not.
-*)
+*)
let full_match closing env = match env with
| ({pat_desc = Tpat_construct ({cstr_tag=Cstr_exception _},_)},_)::_ ->
false
| ({pat_desc = Tpat_construct(c,_)},_) :: _ ->
List.length env = c.cstr_consts + c.cstr_nonconsts
-| ({pat_desc = Tpat_variant(_,_,row)},_) :: _ ->
+| ({pat_desc = Tpat_variant _} as p,_) :: _ ->
let fields =
List.map
(function ({pat_desc = Tpat_variant (tag, _, _)}, _) -> tag
| _ -> assert false)
env
in
- let row = Btype.row_repr row in
+ let row = row_of_pat p in
if closing && not row.row_fixed then
(* closing=true, we are considering the variant as closed *)
List.for_all
@@ -738,17 +743,17 @@ let build_other ext env = match env with
let all_tags = List.map (fun (p,_) -> get_tag p) env in
pat_of_constrs p (complete_constrs p all_tags)
end
-| ({pat_desc = Tpat_variant(_,_,row)} as p,_) :: _ ->
+| ({pat_desc = Tpat_variant (_,_,r)} as p,_) :: _ ->
let tags =
List.map
(function ({pat_desc = Tpat_variant (tag, _, _)}, _) -> tag
| _ -> assert false)
env
in
- let row = Btype.row_repr row in
+ let row = row_of_pat p in
let make_other_pat tag const =
let arg = if const then None else Some omega in
- make_pat (Tpat_variant(tag, arg, row)) p.pat_type p.pat_env in
+ make_pat (Tpat_variant(tag, arg, r)) p.pat_type p.pat_env in
begin match
List.fold_left
(fun others (tag,f) ->
@@ -999,8 +1004,8 @@ let rec pressure_variants tdefs = function
else try_non_omega (filter_all q0 (mark_partial pss))
in
begin match constrs, tdefs with
- ({pat_desc=Tpat_variant(_,_,row)},_):: _, Some env ->
- let row = Btype.row_repr row in
+ ({pat_desc=Tpat_variant _} as p,_):: _, Some env ->
+ let row = row_of_pat p in
if row.row_fixed
|| pressure_variants None (filter_extra pss) then ()
else close_variant env row
diff --git a/typing/printtyp.ml b/typing/printtyp.ml
index c6aec4fc8..5f4d5d0b4 100644
--- a/typing/printtyp.ml
+++ b/typing/printtyp.ml
@@ -246,7 +246,7 @@ let rec mark_loops_rec visited ty =
| Some(p, tyl) when namable_row row ->
List.iter (mark_loops_rec visited) tyl
| _ ->
- iter_row (mark_loops_rec visited) {row with row_bound = []}
+ iter_row (mark_loops_rec visited) row
end
| Tobject (fi, nm) ->
if List.memq px !visited_objects then add_alias px else
diff --git a/typing/subst.ml b/typing/subst.ml
index f959f8af3..6b1282697 100644
--- a/typing/subst.ml
+++ b/typing/subst.ml
@@ -124,8 +124,6 @@ let rec typexp s ty =
(* Return a new copy *)
let row =
copy_row (typexp s) true row (not dup) more' in
- let row =
- if s.for_saving then {row with row_bound = []} else row in
match row.row_name with
Some (p, tl) ->
Tvariant {row with row_name = Some (type_path s p, tl)}
diff --git a/typing/subst.mli b/typing/subst.mli
index b2220bb49..d31385325 100644
--- a/typing/subst.mli
+++ b/typing/subst.mli
@@ -38,6 +38,9 @@ val add_modtype: Ident.t -> module_type -> t -> t
val for_saving: t -> t
val reset_for_saving: unit -> unit
+val module_path: t -> Path.t -> Path.t
+val type_path: t -> Path.t -> Path.t
+
val type_expr: t -> type_expr -> type_expr
val class_type: t -> class_type -> class_type
val value_description: t -> value_description -> value_description
diff --git a/typing/typeclass.ml b/typing/typeclass.ml
index a7ed236f3..a30b2a469 100644
--- a/typing/typeclass.ml
+++ b/typing/typeclass.ml
@@ -673,7 +673,8 @@ and class_structure cl_num final val_env met_env loc (spat, str) =
Vars.fold
(fun name (mut, vr, ty) l -> if vr = Virtual then name :: l else l)
sign.cty_vars [] in
- if mets <> [] then raise(Error(loc, Virtual_class(true, mets, vals)));
+ if mets <> [] || vals <> [] then
+ raise(Error(loc, Virtual_class(true, mets, vals)));
let self_methods =
List.fold_right
(fun (lab,kind,ty) rem ->
@@ -782,7 +783,7 @@ and class_expr cl_num val_env met_env scl =
class_expr cl_num val_env met_env sfun
| Pcl_fun (l, None, spat, scl') ->
if !Clflags.principal then Ctype.begin_def ();
- let (pat, pv, val_env, met_env) =
+ let (pat, pv, val_env', met_env) =
Typecore.type_class_arg_pattern cl_num val_env met_env l spat
in
if !Clflags.principal then begin
@@ -793,7 +794,7 @@ and class_expr cl_num val_env met_env scl =
List.map
(function (id, id', ty) ->
(id,
- Typecore.type_exp val_env
+ Typecore.type_exp val_env'
{pexp_desc = Pexp_ident (Longident.Lident (Ident.name id));
pexp_loc = Location.none}))
pv
@@ -810,7 +811,7 @@ and class_expr cl_num val_env met_env scl =
exp_type = Ctype.none;
exp_env = Env.empty }] in
Ctype.raise_nongen_level ();
- let cl = class_expr cl_num val_env met_env scl' in
+ let cl = class_expr cl_num val_env' met_env scl' in
Ctype.end_def ();
if Btype.is_optional l && not_function cl.cl_type then
Location.prerr_warning pat.pat_loc
diff --git a/typing/typecore.ml b/typing/typecore.ml
index 5865d31ce..2c3a64ec6 100644
--- a/typing/typecore.ml
+++ b/typing/typecore.ml
@@ -30,7 +30,7 @@ type error =
| Constructor_arity_mismatch of Longident.t * int * int
| Label_mismatch of Longident.t * (type_expr * type_expr) list
| Pattern_type_clash of (type_expr * type_expr) list
- | Multiply_bound_variable
+ | Multiply_bound_variable of string
| Orpat_vars of Ident.t
| Expr_type_clash of (type_expr * type_expr) list
| Apply_non_function of type_expr
@@ -152,10 +152,13 @@ let unify_pat env pat expected_ty =
(* make all Reither present in open variants *)
let finalize_variant pat =
match pat.pat_desc with
- Tpat_variant(tag, opat, row) ->
- let row = row_repr row in
- let field = row_field tag row in
- begin match field with
+ Tpat_variant(tag, opat, r) ->
+ let row =
+ match expand_head pat.pat_env pat.pat_type with
+ {desc = Tvariant row} -> r := row; row_repr row
+ | _ -> assert false
+ in
+ begin match row_field tag row with
| Rabsent -> assert false
| Reither (true, [], _, e) when not row.row_closed ->
set_row_field e (Rpresent None)
@@ -168,10 +171,10 @@ let finalize_variant pat =
set_row_field e (Reither (c, [], false, ref None))
| _ -> ()
end;
- (* Force check of well-formedness *)
- unify_pat pat.pat_env pat
+ (* Force check of well-formedness WHY? *)
+ (* unify_pat pat.pat_env pat
(newty(Tvariant{row_fields=[]; row_more=newvar(); row_closed=false;
- row_bound=[]; row_fixed=false; row_name=None}));
+ row_bound=(); row_fixed=false; row_name=None})); *)
| _ -> ()
let rec iter_pattern f p =
@@ -199,7 +202,7 @@ let reset_pattern scope =
let enter_variable loc name ty =
if List.exists (fun (id, _, _) -> Ident.name id = name) !pattern_variables
- then raise(Error(loc, Multiply_bound_variable));
+ then raise(Error(loc, Multiply_bound_variable name));
let id = Ident.create name in
pattern_variables := (id, ty, loc) :: !pattern_variables;
begin match !pattern_scope with
@@ -258,7 +261,7 @@ let rec build_as_type env p =
| Tpat_variant(l, p', _) ->
let ty = may_map (build_as_type env) p' in
newty (Tvariant{row_fields=[l, Rpresent ty]; row_more=newvar();
- row_bound=[]; row_name=None;
+ row_bound=(); row_name=None;
row_fixed=false; row_closed=false})
| Tpat_record lpl ->
let lbl = fst(List.hd lpl) in
@@ -268,7 +271,10 @@ let rec build_as_type env p =
let do_label lbl =
let _, ty_arg, ty_res = instance_label false lbl in
unify_pat env {p with pat_type = ty} ty_res;
- if lbl.lbl_mut = Immutable && List.mem_assoc lbl.lbl_pos ppl then begin
+ let refinable =
+ lbl.lbl_mut = Immutable && List.mem_assoc lbl.lbl_pos ppl &&
+ match (repr lbl.lbl_arg).desc with Tpoly _ -> false | _ -> true in
+ if refinable then begin
let arg = List.assoc lbl.lbl_pos ppl in
unify_pat env {arg with pat_type = build_as_type env arg} ty_arg
end else begin
@@ -278,20 +284,16 @@ let rec build_as_type env p =
end in
Array.iter do_label lbl.lbl_all;
ty
- | Tpat_or(p1, p2, path) ->
- let ty1 = build_as_type env p1 and ty2 = build_as_type env p2 in
- unify_pat env {p2 with pat_type = ty2} ty1;
- begin match path with None -> ()
- | Some path ->
- let td = try Env.find_type path env with Not_found -> assert false in
- let params = List.map (fun _ -> newvar()) td.type_params in
- match expand_head env (newty (Tconstr (path, params, ref Mnil)))
- with {desc=Tvariant row} when static_row row ->
- unify_pat env {p1 with pat_type = ty1}
- (newty (Tvariant{row with row_closed=false; row_more=newvar()}))
- | _ -> ()
- end;
- ty1
+ | Tpat_or(p1, p2, row) ->
+ begin match row with
+ None ->
+ let ty1 = build_as_type env p1 and ty2 = build_as_type env p2 in
+ unify_pat env {p2 with pat_type = ty2} ty1;
+ ty1
+ | Some row ->
+ let row = row_repr row in
+ newty (Tvariant{row with row_closed=false; row_more=newvar()})
+ end
| Tpat_any | Tpat_var _ | Tpat_constant _ | Tpat_array _ -> p.pat_type
let build_or_pat env loc lid =
@@ -301,14 +303,12 @@ let build_or_pat env loc lid =
raise(Typetexp.Error(loc, Typetexp.Unbound_type_constructor lid))
in
let tyl = List.map (fun _ -> newvar()) decl.type_params in
- let fields =
+ let row0 =
let ty = expand_head env (newty(Tconstr(path, tyl, ref Mnil))) in
match ty.desc with
- Tvariant row when static_row row ->
- (row_repr row).row_fields
+ Tvariant row when static_row row -> row
| _ -> raise(Error(loc, Not_a_variant_type lid))
in
- let bound = ref [] in
let pats, fields =
List.fold_left
(fun (pats,fields) (l,f) ->
@@ -317,21 +317,21 @@ let build_or_pat env loc lid =
(l,None) :: pats,
(l, Reither(true,[], true, ref None)) :: fields
| Rpresent (Some ty) ->
- bound := ty :: !bound;
(l, Some {pat_desc=Tpat_any; pat_loc=Location.none; pat_env=env;
pat_type=ty})
:: pats,
(l, Reither(false, [ty], true, ref None)) :: fields
| _ -> pats, fields)
- ([],[]) fields in
+ ([],[]) (row_repr row0).row_fields in
let row =
- { row_fields = List.rev fields; row_more = newvar(); row_bound = !bound;
+ { row_fields = List.rev fields; row_more = newvar(); row_bound = ();
row_closed = false; row_fixed = false; row_name = Some (path, tyl) }
in
let ty = newty (Tvariant row) in
let gloc = {loc with Location.loc_ghost=true} in
+ let row' = ref {row with row_more=newvar()} in
let pats =
- List.map (fun (l,p) -> {pat_desc=Tpat_variant(l,p,row); pat_loc=gloc;
+ List.map (fun (l,p) -> {pat_desc=Tpat_variant(l,p,row'); pat_loc=gloc;
pat_env=env; pat_type=ty})
pats
in
@@ -340,7 +340,7 @@ let build_or_pat env loc lid =
| pat :: pats ->
let r =
List.fold_left
- (fun pat pat0 -> {pat_desc=Tpat_or(pat0,pat,Some path);
+ (fun pat pat0 -> {pat_desc=Tpat_or(pat0,pat,Some row0);
pat_loc=gloc; pat_env=env; pat_type=ty})
pat pats in
rp { r with pat_loc = loc }
@@ -432,13 +432,13 @@ let rec type_pat env sp =
let arg_type = match arg with None -> [] | Some arg -> [arg.pat_type] in
let row = { row_fields =
[l, Reither(arg = None, arg_type, true, ref None)];
- row_bound = arg_type;
+ row_bound = ();
row_closed = false;
row_more = newvar ();
row_fixed = false;
row_name = None } in
rp {
- pat_desc = Tpat_variant(l, arg, row);
+ pat_desc = Tpat_variant(l, arg, ref {row with row_more = newvar()});
pat_loc = sp.ppat_loc;
pat_type = newty (Tvariant row);
pat_env = env }
@@ -594,8 +594,11 @@ let delayed_checks = ref []
let reset_delayed_checks () = delayed_checks := []
let add_delayed_check f = delayed_checks := f :: !delayed_checks
let force_delayed_checks () =
+ (* checks may change type levels *)
+ let snap = Btype.snapshot () in
List.iter (fun f -> f ()) (List.rev !delayed_checks);
- reset_delayed_checks ()
+ reset_delayed_checks ();
+ Btype.backtrack snap
(* Generalization criterion for expressions *)
@@ -624,6 +627,7 @@ let rec is_nonexpansive exp =
| Texp_array [] -> true
| Texp_ifthenelse(cond, ifso, ifnot) ->
is_nonexpansive ifso && is_nonexpansive_opt ifnot
+ | Texp_sequence (e1, e2) -> is_nonexpansive e2 (* PR#4354 *)
| Texp_new (_, cl_decl) when Ctype.class_type_arity cl_decl.cty_type > 0 ->
true
(* Note: nonexpansive only means no _observable_ side effects *)
@@ -1028,7 +1032,7 @@ let rec type_exp env sexp =
exp_loc = sexp.pexp_loc;
exp_type= newty (Tvariant{row_fields = [l, Rpresent arg_type];
row_more = newvar ();
- row_bound = [];
+ row_bound = ();
row_closed = false;
row_fixed = false;
row_name = None});
@@ -2067,8 +2071,8 @@ let report_error ppf = function
fprintf ppf "This pattern matches values of type")
(function ppf ->
fprintf ppf "but is here used to match values of type")
- | Multiply_bound_variable ->
- fprintf ppf "This variable is bound several times in this matching"
+ | Multiply_bound_variable name ->
+ fprintf ppf "Variable %s is bound several times in this matching" name
| Orpat_vars id ->
fprintf ppf "Variable %s must occur on both sides of this | pattern"
(Ident.name id)
diff --git a/typing/typecore.mli b/typing/typecore.mli
index d860f0a85..65ae12b17 100644
--- a/typing/typecore.mli
+++ b/typing/typecore.mli
@@ -70,7 +70,7 @@ type error =
| Constructor_arity_mismatch of Longident.t * int * int
| Label_mismatch of Longident.t * (type_expr * type_expr) list
| Pattern_type_clash of (type_expr * type_expr) list
- | Multiply_bound_variable
+ | Multiply_bound_variable of string
| Orpat_vars of Ident.t
| Expr_type_clash of (type_expr * type_expr) list
| Apply_non_function of type_expr
diff --git a/typing/typedtree.ml b/typing/typedtree.ml
index 942b4ce00..6f5f5d40b 100644
--- a/typing/typedtree.ml
+++ b/typing/typedtree.ml
@@ -33,10 +33,10 @@ and pattern_desc =
| Tpat_constant of constant
| Tpat_tuple of pattern list
| Tpat_construct of constructor_description * pattern list
- | Tpat_variant of label * pattern option * row_desc
+ | Tpat_variant of label * pattern option * row_desc ref
| Tpat_record of (label_description * pattern) list
| Tpat_array of pattern list
- | Tpat_or of pattern * pattern * Path.t option
+ | Tpat_or of pattern * pattern * row_desc option
type partial = Partial | Total
type optional = Required | Optional
diff --git a/typing/typedtree.mli b/typing/typedtree.mli
index ebf8aba70..af8b1a6ef 100644
--- a/typing/typedtree.mli
+++ b/typing/typedtree.mli
@@ -32,10 +32,10 @@ and pattern_desc =
| Tpat_constant of constant
| Tpat_tuple of pattern list
| Tpat_construct of constructor_description * pattern list
- | Tpat_variant of label * pattern option * row_desc
+ | Tpat_variant of label * pattern option * row_desc ref
| Tpat_record of (label_description * pattern) list
| Tpat_array of pattern list
- | Tpat_or of pattern * pattern * Path.t option
+ | Tpat_or of pattern * pattern * row_desc option
type partial = Partial | Total
type optional = Required | Optional
diff --git a/typing/typemod.ml b/typing/typemod.ml
index 70037182c..0552204e0 100644
--- a/typing/typemod.ml
+++ b/typing/typemod.ml
@@ -411,11 +411,19 @@ and transl_recmodule_modtypes loc env sdecls =
(fun (name, smty) ->
(Ident.create name, approx_modtype transl_modtype env smty))
sdecls in
- let first = transition (make_env init) init in
- let final_env = make_env first in
- let final_decl = transition final_env init in
- check_recmod_typedecls final_env sdecls final_decl;
- (final_decl, final_env)
+ let env0 = make_env init in
+ let dcl1 = transition env0 init in
+ let env1 = make_env dcl1 in
+ let dcl2 = transition env1 dcl1 in
+ let env2 = make_env dcl2 in
+ check_recmod_typedecls env2 sdecls dcl2;
+(*
+ List.iter
+ (fun (id, mty) ->
+ Format.printf "%a: %a@." Printtyp.ident id Printtyp.modtype mty)
+ dcl2;
+*)
+ (dcl2, env2)
(* Try to convert a module expression to a module path. *)
@@ -493,6 +501,79 @@ let enrich_module_type anchor name mty env =
None -> mty
| Some p -> Mtype.enrich_modtype env (Pdot(p, name, nopos)) mty
+let check_recmodule_inclusion env bindings =
+ (* PR#4450, PR#4470: consider
+ module rec X : DECL = MOD where MOD has inferred type ACTUAL
+ The "natural" typing condition
+ E, X: ACTUAL |- ACTUAL <: DECL
+ leads to circularities through manifest types.
+ Instead, we "unroll away" the potential circularities a finite number
+ of times. The (weaker) condition we implement is:
+ E, X: DECL,
+ X1: ACTUAL,
+ X2: ACTUAL{X <- X1}/X1
+ ...
+ Xn: ACTUAL{X <- X(n-1)}/X(n-1)
+ |- ACTUAL{X <- Xn}/Xn <: DECL{X <- Xn}
+ so that manifest types rooted at X(n+1) are expanded in terms of X(n),
+ avoiding circularities. The strengthenings ensure that
+ Xn.t = X(n-1).t = ... = X2.t = X1.t.
+ N can be chosen arbitrarily; larger values of N result in more
+ recursive definitions being accepted. A good choice appears to be
+ the number of mutually recursive declarations. *)
+
+ let subst_and_strengthen env s id mty =
+ Mtype.strengthen env (Subst.modtype s mty)
+ (Subst.module_path s (Pident id)) in
+
+ let rec check_incl first_time n env s =
+ if n > 0 then begin
+ (* Generate fresh names Y_i for the rec. bound module idents X_i *)
+ let bindings1 =
+ List.map
+ (fun (id, mty_decl, modl, mty_actual) ->
+ (id, Ident.rename id, mty_actual))
+ bindings in
+ (* Enter the Y_i in the environment with their actual types substituted
+ by the input substitution s *)
+ let env' =
+ List.fold_left
+ (fun env (id, id', mty_actual) ->
+ let mty_actual' =
+ if first_time
+ then mty_actual
+ else subst_and_strengthen env s id mty_actual in
+ Env.add_module id' mty_actual' env)
+ env bindings1 in
+ (* Build the output substitution Y_i <- X_i *)
+ let s' =
+ List.fold_left
+ (fun s (id, id', mty_actual) ->
+ Subst.add_module id (Pident id') s)
+ Subst.identity bindings1 in
+ (* Recurse with env' and s' *)
+ check_incl false (n-1) env' s'
+ end else begin
+ (* Base case: check inclusion of s(mty_actual) in s(mty_decl)
+ and insert coercion if needed *)
+ let check_inclusion (id, mty_decl, modl, mty_actual) =
+ let mty_decl' = Subst.modtype s mty_decl
+ and mty_actual' = subst_and_strengthen env s id mty_actual in
+ let coercion =
+ try
+ Includemod.modtypes env mty_actual' mty_decl'
+ with Includemod.Error msg ->
+ raise(Error(modl.mod_loc, Not_included msg)) in
+ let modl' =
+ { mod_desc = Tmod_constraint(modl, mty_decl, coercion);
+ mod_type = mty_decl;
+ mod_env = env;
+ mod_loc = modl.mod_loc } in
+ (id, modl') in
+ List.map check_inclusion bindings
+ end
+ in check_incl true (List.length bindings) env Subst.identity
+
(* Type a module value expression *)
let rec type_module anchor env smod =
@@ -641,27 +722,21 @@ and type_structure anchor env sstr scope =
let (decls, newenv) =
transl_recmodule_modtypes loc env
(List.map (fun (name, smty, smodl) -> (name, smty)) sbind) in
- let type_recmodule_binding (id, mty) (name, smty, smodl) =
- let modl =
- type_module (anchor_recmodule id anchor) newenv smodl in
- let coercion =
- try
- Includemod.modtypes newenv
- (Mtype.strengthen env modl.mod_type (Pident id))
- mty
- with Includemod.Error msg ->
- raise(Error(smodl.pmod_loc, Not_included msg)) in
- let modl' =
- { mod_desc = Tmod_constraint(modl, mty, coercion);
- mod_type = mty;
- mod_env = newenv;
- mod_loc = smodl.pmod_loc } in
- (id, modl') in
- let bind = List.map2 type_recmodule_binding decls sbind in
+ let bindings1 =
+ List.map2
+ (fun (id, mty) (name, smty, smodl) ->
+ let modl =
+ type_module (anchor_recmodule id anchor) newenv smodl in
+ let mty' =
+ enrich_module_type anchor (Ident.name id) modl.mod_type newenv in
+ (id, mty, modl, mty'))
+ decls sbind in
+ let bindings2 =
+ check_recmodule_inclusion newenv bindings1 in
let (str_rem, sig_rem, final_env) = type_struct newenv srem in
- (Tstr_recmodule bind :: str_rem,
+ (Tstr_recmodule bindings2 :: str_rem,
map_rec (fun rs (id, modl) -> Tsig_module(id, modl.mod_type, rs))
- bind sig_rem,
+ bindings2 sig_rem,
final_env)
| {pstr_desc = Pstr_modtype(name, smty); pstr_loc = loc} :: srem ->
check "module type" loc modtype_names name;
diff --git a/typing/types.ml b/typing/types.ml
index fe876760f..0a6e652ec 100644
--- a/typing/types.ml
+++ b/typing/types.ml
@@ -41,7 +41,7 @@ and type_desc =
and row_desc =
{ row_fields: (label * row_field) list;
row_more: type_expr;
- row_bound: type_expr list;
+ row_bound: unit;
row_closed: bool;
row_fixed: bool;
row_name: (Path.t * type_expr list) option }
diff --git a/typing/types.mli b/typing/types.mli
index 05d205267..26f429496 100644
--- a/typing/types.mli
+++ b/typing/types.mli
@@ -40,7 +40,7 @@ and type_desc =
and row_desc =
{ row_fields: (label * row_field) list;
row_more: type_expr;
- row_bound: type_expr list;
+ row_bound: unit; (* kept for compatibility *)
row_closed: bool;
row_fixed: bool;
row_name: (Path.t * type_expr list) option }
diff --git a/typing/typetexp.ml b/typing/typetexp.ml
index 4f615abbd..33583af50 100644
--- a/typing/typetexp.ml
+++ b/typing/typetexp.ml
@@ -202,14 +202,12 @@ let rec transl_type env policy styp =
(fun l -> if not (List.mem_assoc l row.row_fields) then
raise(Error(styp.ptyp_loc, Present_has_no_type l)))
present;
- let bound = ref row.row_bound in
let fields =
List.map
(fun (l,f) -> l,
if List.mem l present then f else
match Btype.row_field_repr f with
| Rpresent (Some ty) ->
- bound := ty :: !bound;
Reither(false, [ty], false, ref None)
| Rpresent None ->
Reither (true, [], false, ref None)
@@ -217,7 +215,7 @@ let rec transl_type env policy styp =
row.row_fields
in
let row = { row_closed = true; row_fields = fields;
- row_bound = !bound; row_name = Some (path, args);
+ row_bound = (); row_name = Some (path, args);
row_fixed = false; row_more = newvar () } in
let static = Btype.static_row row in
let row =
@@ -262,28 +260,31 @@ let rec transl_type env policy styp =
instance t
end
| Ptyp_variant(fields, closed, present) ->
- let bound = ref [] and name = ref None in
+ let name = ref None in
let mkfield l f =
newty (Tvariant {row_fields=[l,f]; row_more=newvar();
- row_bound=[]; row_closed=true;
+ row_bound=(); row_closed=true;
row_fixed=false; row_name=None}) in
- let add_typed_field loc l f fields =
+ let hfields = Hashtbl.create 17 in
+ let add_typed_field loc l f =
+ let h = Btype.hash_variant l in
try
- let f' = List.assoc l fields in
+ let (l',f') = Hashtbl.find hfields h in
+ (* Check for tag conflicts *)
+ if l <> l' then raise(Error(styp.ptyp_loc, Variant_tags(l, l')));
let ty = mkfield l f and ty' = mkfield l f' in
- if equal env false [ty] [ty'] then fields else
- try unify env ty ty'; fields
+ if equal env false [ty] [ty'] then () else
+ try unify env ty ty'
with Unify trace -> raise(Error(loc, Constructor_mismatch (ty,ty')))
with Not_found ->
- (l, f) :: fields
+ Hashtbl.add hfields h (l,f)
in
- let rec add_field fields = function
+ let rec add_field = function
Rtag (l, c, stl) ->
name := None;
let f = match present with
Some present when not (List.mem l present) ->
let tl = List.map (transl_type env policy) stl in
- bound := tl @ !bound;
Reither(c, tl, false, ref None)
| _ ->
if List.length stl > 1 || c && stl <> [] then
@@ -291,7 +292,7 @@ let rec transl_type env policy styp =
match stl with [] -> Rpresent None
| st :: _ -> Rpresent (Some(transl_type env policy st))
in
- add_typed_field styp.ptyp_loc l f fields
+ add_typed_field styp.ptyp_loc l f
| Rinherit sty ->
let ty = transl_type env policy sty in
let nm =
@@ -299,7 +300,14 @@ let rec transl_type env policy styp =
{desc=Tconstr(p, tl, _)} -> Some(p, tl)
| _ -> None
in
- name := if fields = [] then nm else None;
+ begin try
+ (* Set name if there are no fields yet *)
+ Hashtbl.iter (fun _ _ -> raise Exit) hfields;
+ name := nm
+ with Exit ->
+ (* Unset it otherwise *)
+ name := None
+ end;
let fl = match expand_head env ty, nm with
{desc=Tvariant row}, _ when Btype.static_row row ->
let row = Btype.row_repr row in
@@ -309,13 +317,12 @@ let rec transl_type env policy styp =
| _ ->
raise(Error(sty.ptyp_loc, Not_a_variant ty))
in
- List.fold_left
- (fun fields (l, f) ->
+ List.iter
+ (fun (l, f) ->
let f = match present with
Some present when not (List.mem l present) ->
begin match f with
Rpresent(Some ty) ->
- bound := ty :: !bound;
Reither(false, [ty], false, ref None)
| Rpresent None ->
Reither(true, [], false, ref None)
@@ -324,10 +331,11 @@ let rec transl_type env policy styp =
end
| _ -> f
in
- add_typed_field sty.ptyp_loc l f fields)
- fields fl
+ add_typed_field sty.ptyp_loc l f)
+ fl
in
- let fields = List.fold_left add_field [] fields in
+ List.iter add_field fields;
+ let fields = Hashtbl.fold (fun _ p l -> p :: l) hfields [] in
begin match present with None -> ()
| Some present ->
List.iter
@@ -335,25 +343,18 @@ let rec transl_type env policy styp =
raise(Error(styp.ptyp_loc, Present_has_no_type l)))
present
end;
- (* Check for tag conflicts *)
- let ht = Hashtbl.create (List.length fields + 1) in
- List.iter
- (fun (l,_) ->
- let h = Btype.hash_variant l in
- try
- let l' = Hashtbl.find ht h in
- if l <> l' then raise(Error(styp.ptyp_loc, Variant_tags(l, l')))
- with Not_found ->
- Hashtbl.add ht h l)
- fields;
let row =
{ row_fields = List.rev fields; row_more = newvar ();
- row_bound = !bound; row_closed = closed;
+ row_bound = (); row_closed = closed;
row_fixed = false; row_name = !name } in
let static = Btype.static_row row in
let row =
- if static || policy <> Univars then row
- else { row with row_more = new_pre_univar () }
+ if static then row else
+ match policy with
+ Fixed ->
+ raise (Error (styp.ptyp_loc, Unbound_type_variable ".."))
+ | Extensible -> row
+ | Univars -> { row with row_more = new_pre_univar () }
in
newty (Tvariant row)
| Ptyp_poly(vars, st) ->
diff --git a/utils/ccomp.ml b/utils/ccomp.ml
index 02d6f8835..3cb192e31 100644
--- a/utils/ccomp.ml
+++ b/utils/ccomp.ml
@@ -46,6 +46,10 @@ let quote_prefixed pr lst =
let lst = List.map (fun f -> pr ^ f) lst in
quote_files lst
+let quote_optfile = function
+ | None -> ""
+ | Some f -> Filename.quote f
+
let compile_file name =
command
(Printf.sprintf
diff --git a/utils/ccomp.mli b/utils/ccomp.mli
index 2ffb30383..72ae71314 100644
--- a/utils/ccomp.mli
+++ b/utils/ccomp.mli
@@ -20,6 +20,7 @@ val compile_file: string -> int
val create_archive: string -> string list -> int
val expand_libname: string -> string
val quote_files: string list -> string
+val quote_optfile: string option -> string
(*val make_link_options: string list -> string*)
type link_mode =