summaryrefslogtreecommitdiffstats
path: root/stdlib
diff options
context:
space:
mode:
authorGabriel Scherer <gabriel.scherer@gmail.com>2014-06-09 13:53:45 +0000
committerGabriel Scherer <gabriel.scherer@gmail.com>2014-06-09 13:53:45 +0000
commitbb313fa192eb11593e720c39164a9866092c4f99 (patch)
tree0e6f2b62b8fd3e32cb2944788bc4460d9ae35f4c /stdlib
parentc24c9ac53d6e4badaefc8ce977ad6059a448364a (diff)
Fix PR#6417: sprintf broken when local module named Pervasives is in scope
(Backport from Jacques' commit 4.02@14921) git-svn-id: http://caml.inria.fr/svn/ocaml/trunk@14972 f963ae5c-01c2-4b8c-9fe0-0dff7051ff02
Diffstat (limited to 'stdlib')
-rw-r--r--stdlib/.depend73
-rwxr-xr-xstdlib/Compflags1
-rwxr-xr-xstdlib/Makefile.shared4
-rw-r--r--stdlib/camlinternalFormatBasics.ml604
-rw-r--r--stdlib/camlinternalFormatBasics.mli280
-rw-r--r--stdlib/pervasives.ml607
-rw-r--r--stdlib/pervasives.mli283
7 files changed, 930 insertions, 922 deletions
diff --git a/stdlib/.depend b/stdlib/.depend
index 9ba813de6..e3a0a671d 100644
--- a/stdlib/.depend
+++ b/stdlib/.depend
@@ -5,7 +5,8 @@ buffer.cmi :
bytes.cmi :
bytesLabels.cmi :
callback.cmi :
-camlinternalFormat.cmi : buffer.cmi
+camlinternalFormat.cmi : camlinternalFormatBasics.cmi buffer.cmi
+camlinternalFormatBasics.cmi :
camlinternalLazy.cmi :
camlinternalMod.cmi : obj.cmi
camlinternalOO.cmi : obj.cmi
@@ -30,7 +31,7 @@ nativeint.cmi :
obj.cmi : int32.cmi
oo.cmi : camlinternalOO.cmi
parsing.cmi : obj.cmi lexing.cmi
-pervasives.cmi :
+pervasives.cmi : camlinternalFormatBasics.cmi
printexc.cmi :
printf.cmi : buffer.cmi
queue.cmi :
@@ -62,10 +63,12 @@ bytesLabels.cmo : bytes.cmi bytesLabels.cmi
bytesLabels.cmx : bytes.cmx bytesLabels.cmi
callback.cmo : obj.cmi callback.cmi
callback.cmx : obj.cmx callback.cmi
-camlinternalFormat.cmo : sys.cmi string.cmi char.cmi bytes.cmi buffer.cmi \
- camlinternalFormat.cmi
-camlinternalFormat.cmx : sys.cmx string.cmx char.cmx bytes.cmx buffer.cmx \
- camlinternalFormat.cmi
+camlinternalFormat.cmo : sys.cmi string.cmi char.cmi \
+ camlinternalFormatBasics.cmi bytes.cmi buffer.cmi camlinternalFormat.cmi
+camlinternalFormat.cmx : sys.cmx string.cmx char.cmx \
+ camlinternalFormatBasics.cmx bytes.cmx buffer.cmx camlinternalFormat.cmi
+camlinternalFormatBasics.cmo : camlinternalFormatBasics.cmi
+camlinternalFormatBasics.cmx : camlinternalFormatBasics.cmi
camlinternalLazy.cmo : obj.cmi camlinternalLazy.cmi
camlinternalLazy.cmx : obj.cmx camlinternalLazy.cmi
camlinternalMod.cmo : obj.cmi camlinternalOO.cmi array.cmi \
@@ -86,10 +89,10 @@ filename.cmo : sys.cmi string.cmi random.cmi printf.cmi lazy.cmi buffer.cmi \
filename.cmi
filename.cmx : sys.cmx string.cmx random.cmx printf.cmx lazy.cmx buffer.cmx \
filename.cmi
-format.cmo : string.cmi pervasives.cmi camlinternalFormat.cmi buffer.cmi \
- format.cmi
-format.cmx : string.cmx pervasives.cmx camlinternalFormat.cmx buffer.cmx \
- format.cmi
+format.cmo : string.cmi pervasives.cmi camlinternalFormatBasics.cmi \
+ camlinternalFormat.cmi buffer.cmi format.cmi
+format.cmx : string.cmx pervasives.cmx camlinternalFormatBasics.cmx \
+ camlinternalFormat.cmx buffer.cmx format.cmi
gc.cmo : sys.cmi printf.cmi gc.cmi
gc.cmx : sys.cmx printf.cmx gc.cmi
genlex.cmo : string.cmi stream.cmi list.cmi hashtbl.cmi char.cmi bytes.cmi \
@@ -126,14 +129,16 @@ oo.cmo : camlinternalOO.cmi oo.cmi
oo.cmx : camlinternalOO.cmx oo.cmi
parsing.cmo : obj.cmi lexing.cmi array.cmi parsing.cmi
parsing.cmx : obj.cmx lexing.cmx array.cmx parsing.cmi
-pervasives.cmo : pervasives.cmi
-pervasives.cmx : pervasives.cmi
+pervasives.cmo : camlinternalFormatBasics.cmi pervasives.cmi
+pervasives.cmx : camlinternalFormatBasics.cmx pervasives.cmi
printexc.cmo : printf.cmi pervasives.cmi obj.cmi buffer.cmi array.cmi \
printexc.cmi
printexc.cmx : printf.cmx pervasives.cmx obj.cmx buffer.cmx array.cmx \
printexc.cmi
-printf.cmo : camlinternalFormat.cmi buffer.cmi printf.cmi
-printf.cmx : camlinternalFormat.cmx buffer.cmx printf.cmi
+printf.cmo : camlinternalFormatBasics.cmi camlinternalFormat.cmi buffer.cmi \
+ printf.cmi
+printf.cmx : camlinternalFormatBasics.cmx camlinternalFormat.cmx buffer.cmx \
+ printf.cmi
queue.cmo : obj.cmi queue.cmi
queue.cmx : obj.cmx queue.cmi
random.cmo : string.cmi pervasives.cmi nativeint.cmi int64.cmi int32.cmi \
@@ -141,9 +146,11 @@ random.cmo : string.cmi pervasives.cmi nativeint.cmi int64.cmi int32.cmi \
random.cmx : string.cmx pervasives.cmx nativeint.cmx int64.cmx int32.cmx \
digest.cmx char.cmx array.cmx random.cmi
scanf.cmo : string.cmi printf.cmi pervasives.cmi list.cmi \
- camlinternalFormat.cmi bytes.cmi buffer.cmi scanf.cmi
+ camlinternalFormatBasics.cmi camlinternalFormat.cmi bytes.cmi buffer.cmi \
+ scanf.cmi
scanf.cmx : string.cmx printf.cmx pervasives.cmx list.cmx \
- camlinternalFormat.cmx bytes.cmx buffer.cmx scanf.cmi
+ camlinternalFormatBasics.cmx camlinternalFormat.cmx bytes.cmx buffer.cmx \
+ scanf.cmi
set.cmo : list.cmi set.cmi
set.cmx : list.cmx set.cmi
sort.cmo : array.cmi sort.cmi
@@ -182,10 +189,12 @@ bytesLabels.cmo : bytes.cmi bytesLabels.cmi
bytesLabels.p.cmx : bytes.p.cmx bytesLabels.cmi
callback.cmo : obj.cmi callback.cmi
callback.p.cmx : obj.p.cmx callback.cmi
-camlinternalFormat.cmo : sys.cmi string.cmi char.cmi bytes.cmi buffer.cmi \
- camlinternalFormat.cmi
-camlinternalFormat.p.cmx : sys.p.cmx string.p.cmx char.p.cmx bytes.p.cmx buffer.p.cmx \
- camlinternalFormat.cmi
+camlinternalFormat.cmo : sys.cmi string.cmi char.cmi \
+ camlinternalFormatBasics.cmi bytes.cmi buffer.cmi camlinternalFormat.cmi
+camlinternalFormat.p.cmx : sys.p.cmx string.p.cmx char.p.cmx \
+ camlinternalFormatBasics.p.cmx bytes.p.cmx buffer.p.cmx camlinternalFormat.cmi
+camlinternalFormatBasics.cmo : camlinternalFormatBasics.cmi
+camlinternalFormatBasics.p.cmx : camlinternalFormatBasics.cmi
camlinternalLazy.cmo : obj.cmi camlinternalLazy.cmi
camlinternalLazy.p.cmx : obj.p.cmx camlinternalLazy.cmi
camlinternalMod.cmo : obj.cmi camlinternalOO.cmi array.cmi \
@@ -206,10 +215,10 @@ filename.cmo : sys.cmi string.cmi random.cmi printf.cmi lazy.cmi buffer.cmi \
filename.cmi
filename.p.cmx : sys.p.cmx string.p.cmx random.p.cmx printf.p.cmx lazy.p.cmx buffer.p.cmx \
filename.cmi
-format.cmo : string.cmi pervasives.cmi camlinternalFormat.cmi buffer.cmi \
- format.cmi
-format.p.cmx : string.p.cmx pervasives.p.cmx camlinternalFormat.p.cmx buffer.p.cmx \
- format.cmi
+format.cmo : string.cmi pervasives.cmi camlinternalFormatBasics.cmi \
+ camlinternalFormat.cmi buffer.cmi format.cmi
+format.p.cmx : string.p.cmx pervasives.p.cmx camlinternalFormatBasics.p.cmx \
+ camlinternalFormat.p.cmx buffer.p.cmx format.cmi
gc.cmo : sys.cmi printf.cmi gc.cmi
gc.p.cmx : sys.p.cmx printf.p.cmx gc.cmi
genlex.cmo : string.cmi stream.cmi list.cmi hashtbl.cmi char.cmi bytes.cmi \
@@ -246,14 +255,16 @@ oo.cmo : camlinternalOO.cmi oo.cmi
oo.p.cmx : camlinternalOO.p.cmx oo.cmi
parsing.cmo : obj.cmi lexing.cmi array.cmi parsing.cmi
parsing.p.cmx : obj.p.cmx lexing.p.cmx array.p.cmx parsing.cmi
-pervasives.cmo : pervasives.cmi
-pervasives.p.cmx : pervasives.cmi
+pervasives.cmo : camlinternalFormatBasics.cmi pervasives.cmi
+pervasives.p.cmx : camlinternalFormatBasics.p.cmx pervasives.cmi
printexc.cmo : printf.cmi pervasives.cmi obj.cmi buffer.cmi array.cmi \
printexc.cmi
printexc.p.cmx : printf.p.cmx pervasives.p.cmx obj.p.cmx buffer.p.cmx array.p.cmx \
printexc.cmi
-printf.cmo : camlinternalFormat.cmi buffer.cmi printf.cmi
-printf.p.cmx : camlinternalFormat.p.cmx buffer.p.cmx printf.cmi
+printf.cmo : camlinternalFormatBasics.cmi camlinternalFormat.cmi buffer.cmi \
+ printf.cmi
+printf.p.cmx : camlinternalFormatBasics.p.cmx camlinternalFormat.p.cmx buffer.p.cmx \
+ printf.cmi
queue.cmo : obj.cmi queue.cmi
queue.p.cmx : obj.p.cmx queue.cmi
random.cmo : string.cmi pervasives.cmi nativeint.cmi int64.cmi int32.cmi \
@@ -261,9 +272,11 @@ random.cmo : string.cmi pervasives.cmi nativeint.cmi int64.cmi int32.cmi \
random.p.cmx : string.p.cmx pervasives.p.cmx nativeint.p.cmx int64.p.cmx int32.p.cmx \
digest.p.cmx char.p.cmx array.p.cmx random.cmi
scanf.cmo : string.cmi printf.cmi pervasives.cmi list.cmi \
- camlinternalFormat.cmi bytes.cmi buffer.cmi scanf.cmi
+ camlinternalFormatBasics.cmi camlinternalFormat.cmi bytes.cmi buffer.cmi \
+ scanf.cmi
scanf.p.cmx : string.p.cmx printf.p.cmx pervasives.p.cmx list.p.cmx \
- camlinternalFormat.p.cmx bytes.p.cmx buffer.p.cmx scanf.cmi
+ camlinternalFormatBasics.p.cmx camlinternalFormat.p.cmx bytes.p.cmx buffer.p.cmx \
+ scanf.cmi
set.cmo : list.cmi set.cmi
set.p.cmx : list.p.cmx set.cmi
sort.cmo : array.cmi sort.cmi
diff --git a/stdlib/Compflags b/stdlib/Compflags
index 7c023d98b..f393c4ec0 100755
--- a/stdlib/Compflags
+++ b/stdlib/Compflags
@@ -20,6 +20,7 @@ case $1 in
# make sure add_char is inlined (PR#5872)
buffer.cm[io]) echo ' -w A';;
camlinternalFormat.cm[io]) echo ' -w Ae';;
+ camlinternalFormatBasics*.cm[iox]) echo ' -nopervasives';;
printf.cm[io]|format.cm[io]|scanf.cm[io]) echo ' -w Ae';;
scanf.cmx|scanf.p.cmx) echo ' -inline 9';;
*Labels.cm[ox]|*Labels.p.cmx) echo ' -nolabels -no-alias-deps';;
diff --git a/stdlib/Makefile.shared b/stdlib/Makefile.shared
index 61f40fe1f..54de337cb 100755
--- a/stdlib/Makefile.shared
+++ b/stdlib/Makefile.shared
@@ -21,7 +21,7 @@ OPTCOMPILER=../ocamlopt
CAMLOPT=$(RUNTIME) $(OPTCOMPILER)
CAMLDEP=../boot/ocamlrun ../tools/ocamldep
-OBJS=pervasives.cmo $(OTHERS)
+OBJS=camlinternalFormatBasics.cmo pervasives.cmo $(OTHERS)
OTHERS=array.cmo list.cmo char.cmo bytes.cmo string.cmo sys.cmo \
sort.cmo marshal.cmo obj.cmo \
int32.cmo int64.cmo nativeint.cmo \
@@ -88,7 +88,7 @@ $(OBJS:.cmo=.cmx) std_exit.cmx: $(OPTCOMPILER)
$(OBJS:.cmo=.p.cmx) std_exit.p.cmx: $(OPTCOMPILER)
# Dependencies on Pervasives (not tracked by ocamldep)
-$(OBJS) std_exit.cmo: pervasives.cmi
+$(OTHERS) std_exit.cmo: pervasives.cmi
$(OTHERS:.cmo=.cmi) std_exit.cmi: pervasives.cmi
$(OBJS:.cmo=.cmx) std_exit.cmx: pervasives.cmi
$(OBJS:.cmo=.p.cmx) std_exit.p.cmx: pervasives.cmi
diff --git a/stdlib/camlinternalFormatBasics.ml b/stdlib/camlinternalFormatBasics.ml
new file mode 100644
index 000000000..76f3a4acc
--- /dev/null
+++ b/stdlib/camlinternalFormatBasics.ml
@@ -0,0 +1,604 @@
+(* Type of a block used by the Format pretty-printer. *)
+type block_type =
+ | Pp_hbox (* Horizontal block no line breaking *)
+ | Pp_vbox (* Vertical block each break leads to a new line *)
+ | Pp_hvbox (* Horizontal-vertical block: same as vbox, except if this block
+ is small enough to fit on a single line *)
+ | Pp_hovbox (* Horizontal or Vertical block: breaks lead to new line
+ only when necessary to print the content of the block *)
+ | Pp_box (* Horizontal or Indent block: breaks lead to new line
+ only when necessary to print the content of the block, or
+ when it leads to a new indentation of the current line *)
+ | Pp_fits (* Internal usage: when a block fits on a single line *)
+
+(* Formatting element used by the Format pretty-printter. *)
+type formatting =
+ | Open_box of string * block_type * int (* @[ *)
+ | Close_box (* @] *)
+ | Open_tag of string * string (* @{ *)
+ | Close_tag (* @} *)
+ | Break of string * int * int (* @, | @ | @; | @;<> *)
+ | FFlush (* @? *)
+ | Force_newline (* @\n *)
+ | Flush_newline (* @. *)
+ | Magic_size of string * int (* @<n> *)
+ | Escaped_at (* @@ *)
+ | Escaped_percent (* @%% *)
+ | Scan_indic of char (* @X *)
+
+(***)
+
+(* Padding position. *)
+type padty =
+ | Left (* Text is left justified ('-' option). *)
+ | Right (* Text is right justified (no '-' option). *)
+ | Zeros (* Text is right justified by zeros (see '0' option). *)
+
+(***)
+
+(* Integer conversion. *)
+type int_conv =
+ | Int_d | Int_pd | Int_sd (* %d | %+d | % d *)
+ | Int_i | Int_pi | Int_si (* %i | %+i | % i *)
+ | Int_x | Int_Cx (* %x | %#x *)
+ | Int_X | Int_CX (* %X | %#X *)
+ | Int_o | Int_Co (* %o | %#o *)
+ | Int_u (* %u *)
+
+(* Float conversion. *)
+type float_conv =
+ | Float_f | Float_pf | Float_sf (* %f | %+f | % f *)
+ | Float_e | Float_pe | Float_se (* %e | %+e | % e *)
+ | Float_E | Float_pE | Float_sE (* %E | %+E | % E *)
+ | Float_g | Float_pg | Float_sg (* %g | %+g | % g *)
+ | Float_G | Float_pG | Float_sG (* %G | %+G | % G *)
+ | Float_F (* %F *)
+
+(***)
+
+(* Char sets (see %[...]) are bitmaps implemented as 32-char strings. *)
+type char_set = string
+
+(***)
+
+(* Counter used in Scanf. *)
+type counter =
+ | Line_counter (* %l *)
+ | Char_counter (* %n *)
+ | Token_counter (* %N, %L *)
+
+(***)
+
+(* Padding of strings and numbers. *)
+type ('a, 'b) padding =
+ (* No padding (ex: "%d") *)
+ | No_padding : ('a, 'a) padding
+ (* Literal padding (ex: "%8d") *)
+ | Lit_padding : padty * int -> ('a, 'a) padding
+ (* Padding as extra argument (ex: "%*d") *)
+ | Arg_padding : padty -> (int -> 'a, 'a) padding
+
+(* Some formats, such as %_d,
+ only accept an optional number as padding option (no extra argument) *)
+type pad_option = int option
+
+(* Precision of floats and '0'-padding of integers. *)
+type ('a, 'b) precision =
+ (* No precision (ex: "%f") *)
+ | No_precision : ('a, 'a) precision
+ (* Literal precision (ex: "%.3f") *)
+ | Lit_precision : int -> ('a, 'a) precision
+ (* Precision as extra argument (ex: "%.*f") *)
+ | Arg_precision : (int -> 'a, 'a) precision
+
+(* Some formats, such as %_f,
+ only accept an optional number as precision option (no extra argument) *)
+type prec_option = int option
+
+(***)
+
+(* Relational format types
+
+In the first format+gadts implementation, the type for %(..%) in the
+fmt GADT was as follows:
+
+| Format_subst : (* %(...%) *)
+ pad_option * ('d1, 'q1, 'd2, 'q2) reader_nb_unifier *
+ ('x, 'b, 'c, 'd1, 'q1, 'u) fmtty *
+ ('u, 'b, 'c, 'q1, 'e1, 'f) fmt ->
+ (('x, 'b, 'c, 'd2, 'q2, 'u) format6 -> 'x, 'b, 'c, 'd1, 'e1, 'f) fmt
+
+Notice that the 'u parameter in 'f position in the format argument
+(('x, .., 'u) format6 -> ..) is equal to the 'u parameter in 'a
+position in the format tail (('u, .., 'f) fmt). This means that the
+type of the expected format parameter depends of where the %(...%)
+are in the format string:
+
+ # Printf.printf "%(%)";;
+ - : (unit, out_channel, unit, '_a, '_a, unit)
+ CamlinternalFormatBasics.format6 -> unit
+ = <fun>
+ # Printf.printf "%(%)%d";;
+ - : (int -> unit, out_channel, unit, '_a, '_a, int -> unit)
+ CamlinternalFormatBasics.format6 -> int -> unit
+ = <fun>
+
+On the contrary, the legacy typer gives a clever type that does not
+depend on the position of %(..%) in the format string. For example,
+%(%) will have the polymorphic type ('a, 'b, 'c, 'd, 'd, 'a): it can
+be concatenated to any format type, and only enforces the constraint
+that its 'a and 'f parameters are equal (no format arguments) and 'd
+and 'e are equal (no reader argument).
+
+The weakening of this parameter type in the GADT version broke user
+code (in fact it essentially made %(...%) unusable except at the last
+position of a format). In particular, the following would not work
+anymore:
+
+ fun sep ->
+ Format.printf "foo%(%)bar%(%)baz" sep sep
+
+As the type-checker would require two *incompatible* types for the %(%)
+in different positions.
+
+The solution to regain a general type for %(..%) is to generalize this
+technique, not only on the 'd, 'e parameters, but on all six
+parameters of a format: we introduce a "relational" type
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+whose values are proofs that ('a1, .., 'f1) and ('a2, .., 'f2) morally
+correspond to the same format type: 'a1 is obtained from 'f1,'b1,'c1
+in the exact same way that 'a2 is obtained from 'f2,'b2,'c2, etc.
+
+For example, the relation between two format types beginning with a Char
+parameter is as follows:
+
+| Char_ty : (* %c *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (char -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ char -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+
+In the general case, the term structure of fmtty_rel is (almost¹)
+isomorphic to the fmtty of the previous implementation: every
+constructor is re-read with a binary, relational type, instead of the
+previous unary typing. fmtty can then be re-defined as the diagonal of
+fmtty_rel:
+
+ type ('a, 'b, 'c, 'd, 'e, 'f) fmtty =
+ ('a, 'b, 'c, 'd, 'e, 'f,
+ 'a, 'b, 'c, 'd, 'e, 'f) fmtty_rel
+
+Once we have this fmtty_rel type in place, we can give the more
+general type to %(...%):
+
+| Format_subst : (* %(...%) *)
+ pad_option *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b, 'c, 'j2, 'd, 'a) fmtty_rel *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b, 'c, 'j2, 'e, 'f) fmt
+
+We accept any format (('g, 'h, 'i, 'j, 'k, 'l) format6) (this is
+completely unrelated to the type of the current format), but also
+require a proof that this format is in relation to another format that
+is concatenable to the format tail. When executing a %(...%) format
+(in camlinternalFormat.ml:make_printf or scanf.ml:make_scanf), we
+transtype the format along this relation using the 'recast' function
+to transpose between related format types.
+
+ val recast :
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1) fmt
+ -> ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ -> ('a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmt
+
+NOTE ¹: the typing of Format_subst_ty requires not one format type, but
+two, one to establish the link between the format argument and the
+first six parameters, and the other for the link between the format
+argumant and the last six parameters.
+
+| Format_subst_ty : (* %(...%) *)
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g1, 'b1, 'c1, 'j1, 'd1, 'a1) fmtty_rel *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g1, 'b1, 'c1, 'j1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
+
+When we generate a format AST, we generate exactly the same witness
+for both relations, and the witness-conversion functions in
+camlinternalFormat do rely on this invariant. For example, the
+function that proves that the relation is transitive
+
+ val trans :
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ -> ('a2, 'b2, 'c2, 'd2, 'e2, 'f2,
+ 'a3, 'b3, 'c3, 'd3, 'e3, 'f3) fmtty_rel
+ -> ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a3, 'b3, 'c3, 'd3, 'e3, 'f3) fmtty_rel
+
+does assume that the two input have exactly the same term structure
+(and is only every used for argument witnesses of the
+Format_subst_ty constructor).
+*)
+
+(* List of format type elements. *)
+(* In particular used to represent %(...%) and %{...%} contents. *)
+type ('a, 'b, 'c, 'd, 'e, 'f) fmtty =
+ ('a, 'b, 'c, 'd, 'e, 'f,
+ 'a, 'b, 'c, 'd, 'e, 'f) fmtty_rel
+and ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel =
+ | Char_ty : (* %c *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (char -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ char -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | String_ty : (* %s *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (string -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ string -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Int_ty : (* %d *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Int32_ty : (* %ld *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int32 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int32 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Nativeint_ty : (* %nd *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (nativeint -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ nativeint -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Int64_ty : (* %Ld *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int64 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int64 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Float_ty : (* %f *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (float -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ float -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Bool_ty : (* %B *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (bool -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ bool -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+
+ | Format_arg_ty : (* %{...%} *)
+ ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Format_subst_ty : (* %(...%) *)
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g1, 'b1, 'c1, 'j1, 'd1, 'a1) fmtty_rel *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g1, 'b1, 'c1, 'j1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
+
+ (* Printf and Format specific constructors. *)
+ | Alpha_ty : (* %a *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('b1 -> 'x -> 'c1) -> 'x -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('b2 -> 'x -> 'c2) -> 'x -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Theta_ty : (* %t *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('b1 -> 'c1) -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('b2 -> 'c2) -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+
+ (* Scanf specific constructor. *)
+ | Reader_ty : (* %r *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('x -> 'a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
+ 'x -> 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
+ | Ignored_reader_ty : (* %_r *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
+
+ | End_of_fmtty :
+ ('f1, 'b1, 'c1, 'd1, 'd1, 'f1,
+ 'f2, 'b2, 'c2, 'd2, 'd2, 'f2) fmtty_rel
+
+(***)
+
+(* List of format elements. *)
+and ('a, 'b, 'c, 'd, 'e, 'f) fmt =
+ | Char : (* %c *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Caml_char : (* %C *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | String : (* %s *)
+ ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Caml_string : (* %S *)
+ ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Int : (* %[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Int32 : (* %l[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int32 -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Nativeint : (* %n[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, nativeint -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Int64 : (* %L[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int64 -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Float : (* %[feEgGF] *)
+ float_conv * ('x, 'y) padding * ('y, float -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Bool : (* %[bB] *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (bool -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Flush : (* %! *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ | String_literal : (* abc *)
+ string * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Char_literal : (* x *)
+ char * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ | Format_arg : (* %{...%} *)
+ pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Format_subst : (* %(...%) *)
+ pad_option *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b, 'c, 'j2, 'd, 'a) fmtty_rel *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b, 'c, 'j2, 'e, 'f) fmt
+
+ (* Printf and Format specific constructor. *)
+ | Alpha : (* %a *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('b -> 'x -> 'c) -> 'x -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Theta : (* %t *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('b -> 'c) -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ (* Format specific constructor: *)
+ | Formatting : (* @_ *)
+ formatting * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ (* Scanf specific constructors: *)
+ | Reader : (* %r *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x -> 'a, 'b, 'c, ('b -> 'x) -> 'd, 'e, 'f) fmt
+ | Scan_char_set : (* %[...] *)
+ pad_option * char_set * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (string -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Scan_get_counter : (* %[nlNL] *)
+ counter * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (int -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Ignored_param : (* %_ *)
+ ('a, 'b, 'c, 'd, 'y, 'x) ignored * ('x, 'b, 'c, 'y, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ | End_of_format :
+ ('f, 'b, 'c, 'e, 'e, 'f) fmt
+
+(***)
+
+(* Type for ignored parameters (see "%_"). *)
+and ('a, 'b, 'c, 'd, 'e, 'f) ignored =
+ | Ignored_char : (* %_c *)
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_caml_char : (* %_C *)
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_string : (* %_s *)
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_caml_string : (* %_S *)
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int : (* %_d *)
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int32 : (* %_ld *)
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_nativeint : (* %_nd *)
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int64 : (* %_Ld *)
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_float : (* %_f *)
+ pad_option * prec_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_bool : (* %_B *)
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_format_arg : (* %_{...%} *)
+ pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty ->
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_format_subst : (* %_(...%) *)
+ pad_option * ('a, 'b, 'c, 'd, 'e, 'f) fmtty ->
+ ('a, 'b, 'c, 'd, 'e, 'f) ignored
+ | Ignored_reader : (* %_r *)
+ ('a, 'b, 'c, ('b -> 'x) -> 'd, 'd, 'a) ignored
+ | Ignored_scan_char_set : (* %_[...] *)
+ pad_option * char_set -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_scan_get_counter : (* %_[nlNL] *)
+ counter -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+
+and ('a, 'b, 'c, 'd, 'e, 'f) format6 =
+ Format of ('a, 'b, 'c, 'd, 'e, 'f) fmt * string
+
+let rec erase_rel : type a b c d e f g h i j k l .
+ (a, b, c, d, e, f,
+ g, h, i, j, k, l) fmtty_rel -> (a, b, c, d, e, f) fmtty
+= function
+ | Char_ty rest ->
+ Char_ty (erase_rel rest)
+ | String_ty rest ->
+ String_ty (erase_rel rest)
+ | Int_ty rest ->
+ Int_ty (erase_rel rest)
+ | Int32_ty rest ->
+ Int32_ty (erase_rel rest)
+ | Int64_ty rest ->
+ Int64_ty (erase_rel rest)
+ | Nativeint_ty rest ->
+ Nativeint_ty (erase_rel rest)
+ | Float_ty rest ->
+ Float_ty (erase_rel rest)
+ | Bool_ty rest ->
+ Bool_ty (erase_rel rest)
+ | Format_arg_ty (ty, rest) ->
+ Format_arg_ty (ty, erase_rel rest)
+ | Format_subst_ty (ty1, ty2, rest) ->
+ Format_subst_ty (ty1, ty1, erase_rel rest)
+ | Alpha_ty rest ->
+ Alpha_ty (erase_rel rest)
+ | Theta_ty rest ->
+ Theta_ty (erase_rel rest)
+ | Reader_ty rest ->
+ Reader_ty (erase_rel rest)
+ | Ignored_reader_ty rest ->
+ Ignored_reader_ty (erase_rel rest)
+ | End_of_fmtty -> End_of_fmtty
+
+(******************************************************************************)
+ (* Format type concatenation *)
+
+(* Concatenate two format types. *)
+(* Used by:
+ * reader_nb_unifier_of_fmtty to count readers in an fmtty,
+ * Scanf.take_fmtty_format_readers to extract readers inside %(...%),
+ * CamlinternalFormat.fmtty_of_ignored_format to extract format type. *)
+
+(*
+let rec concat_fmtty : type a b c d e f g h .
+ (a, b, c, d, e, f) fmtty ->
+ (f, b, c, e, g, h) fmtty ->
+ (a, b, c, d, g, h) fmtty =
+*)
+let rec concat_fmtty :
+ type a1 b1 c1 d1 e1 f1
+ a2 b2 c2 d2 e2 f2
+ g1 j1 g2 j2
+ .
+ (g1, b1, c1, j1, d1, a1,
+ g2, b2, c2, j2, d2, a2) fmtty_rel ->
+ (a1, b1, c1, d1, e1, f1,
+ a2, b2, c2, d2, e2, f2) fmtty_rel ->
+ (g1, b1, c1, j1, e1, f1,
+ g2, b2, c2, j2, e2, f2) fmtty_rel =
+fun fmtty1 fmtty2 -> match fmtty1 with
+ | Char_ty rest ->
+ Char_ty (concat_fmtty rest fmtty2)
+ | String_ty rest ->
+ String_ty (concat_fmtty rest fmtty2)
+ | Int_ty rest ->
+ Int_ty (concat_fmtty rest fmtty2)
+ | Int32_ty rest ->
+ Int32_ty (concat_fmtty rest fmtty2)
+ | Nativeint_ty rest ->
+ Nativeint_ty (concat_fmtty rest fmtty2)
+ | Int64_ty rest ->
+ Int64_ty (concat_fmtty rest fmtty2)
+ | Float_ty rest ->
+ Float_ty (concat_fmtty rest fmtty2)
+ | Bool_ty rest ->
+ Bool_ty (concat_fmtty rest fmtty2)
+ | Alpha_ty rest ->
+ Alpha_ty (concat_fmtty rest fmtty2)
+ | Theta_ty rest ->
+ Theta_ty (concat_fmtty rest fmtty2)
+ | Reader_ty rest ->
+ Reader_ty (concat_fmtty rest fmtty2)
+ | Ignored_reader_ty rest ->
+ Ignored_reader_ty (concat_fmtty rest fmtty2)
+ | Format_arg_ty (ty, rest) ->
+ Format_arg_ty (ty, concat_fmtty rest fmtty2)
+ | Format_subst_ty (ty1, ty2, rest) ->
+ Format_subst_ty (ty1, ty2, concat_fmtty rest fmtty2)
+ | End_of_fmtty -> fmtty2
+
+(******************************************************************************)
+ (* Format concatenation *)
+
+(* Concatenate two formats. *)
+let rec concat_fmt : type a b c d e f g h .
+ (a, b, c, d, e, f) fmt ->
+ (f, b, c, e, g, h) fmt ->
+ (a, b, c, d, g, h) fmt =
+fun fmt1 fmt2 -> match fmt1 with
+ | String (pad, rest) ->
+ String (pad, concat_fmt rest fmt2)
+ | Caml_string (pad, rest) ->
+ Caml_string (pad, concat_fmt rest fmt2)
+
+ | Int (iconv, pad, prec, rest) ->
+ Int (iconv, pad, prec, concat_fmt rest fmt2)
+ | Int32 (iconv, pad, prec, rest) ->
+ Int32 (iconv, pad, prec, concat_fmt rest fmt2)
+ | Nativeint (iconv, pad, prec, rest) ->
+ Nativeint (iconv, pad, prec, concat_fmt rest fmt2)
+ | Int64 (iconv, pad, prec, rest) ->
+ Int64 (iconv, pad, prec, concat_fmt rest fmt2)
+ | Float (fconv, pad, prec, rest) ->
+ Float (fconv, pad, prec, concat_fmt rest fmt2)
+
+ | Char (rest) ->
+ Char (concat_fmt rest fmt2)
+ | Caml_char rest ->
+ Caml_char (concat_fmt rest fmt2)
+ | Bool rest ->
+ Bool (concat_fmt rest fmt2)
+ | Alpha rest ->
+ Alpha (concat_fmt rest fmt2)
+ | Theta rest ->
+ Theta (concat_fmt rest fmt2)
+ | Reader rest ->
+ Reader (concat_fmt rest fmt2)
+ | Flush rest ->
+ Flush (concat_fmt rest fmt2)
+
+ | String_literal (str, rest) ->
+ String_literal (str, concat_fmt rest fmt2)
+ | Char_literal (chr, rest) ->
+ Char_literal (chr, concat_fmt rest fmt2)
+
+ | Format_arg (pad, fmtty, rest) ->
+ Format_arg (pad, fmtty, concat_fmt rest fmt2)
+ | Format_subst (pad, fmtty, rest) ->
+ Format_subst (pad, fmtty, concat_fmt rest fmt2)
+
+ | Scan_char_set (width_opt, char_set, rest) ->
+ Scan_char_set (width_opt, char_set, concat_fmt rest fmt2)
+ | Scan_get_counter (counter, rest) ->
+ Scan_get_counter (counter, concat_fmt rest fmt2)
+ | Ignored_param (ign, rest) ->
+ Ignored_param (ign, concat_fmt rest fmt2)
+
+ | Formatting (fmting, rest) ->
+ Formatting (fmting, concat_fmt rest fmt2)
+
+ | End_of_format ->
+ fmt2
diff --git a/stdlib/camlinternalFormatBasics.mli b/stdlib/camlinternalFormatBasics.mli
new file mode 100644
index 000000000..e45f6bc1f
--- /dev/null
+++ b/stdlib/camlinternalFormatBasics.mli
@@ -0,0 +1,280 @@
+(* No comments, OCaml stdlib internal use only. *)
+
+type block_type = Pp_hbox | Pp_vbox | Pp_hvbox | Pp_hovbox | Pp_box | Pp_fits
+
+type formatting =
+ | Open_box of string * block_type * int
+ | Close_box
+ | Open_tag of string * string
+ | Close_tag
+ | Break of string * int * int
+ | FFlush
+ | Force_newline
+ | Flush_newline
+ | Magic_size of string * int
+ | Escaped_at
+ | Escaped_percent
+ | Scan_indic of char
+
+type padty = Left | Right | Zeros
+
+type int_conv =
+ | Int_d | Int_pd | Int_sd | Int_i | Int_pi | Int_si
+ | Int_x | Int_Cx | Int_X | Int_CX | Int_o | Int_Co | Int_u
+
+type float_conv =
+ | Float_f | Float_pf | Float_sf | Float_e | Float_pe | Float_se
+ | Float_E | Float_pE | Float_sE | Float_g | Float_pg | Float_sg
+ | Float_G | Float_pG | Float_sG | Float_F
+
+type char_set = string
+
+type counter = Line_counter | Char_counter | Token_counter
+
+type ('a, 'b) padding =
+ | No_padding : ('a, 'a) padding
+ | Lit_padding : padty * int -> ('a, 'a) padding
+ | Arg_padding : padty -> (int -> 'a, 'a) padding
+
+type pad_option = int option
+
+type ('a, 'b) precision =
+ | No_precision : ('a, 'a) precision
+ | Lit_precision : int -> ('a, 'a) precision
+ | Arg_precision : (int -> 'a, 'a) precision
+
+type prec_option = int option
+
+type ('a, 'b, 'c, 'd, 'e, 'f) fmtty =
+ ('a, 'b, 'c, 'd, 'e, 'f,
+ 'a, 'b, 'c, 'd, 'e, 'f) fmtty_rel
+and ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel =
+ | Char_ty : (* %c *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (char -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ char -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | String_ty : (* %s *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (string -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ string -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Int_ty : (* %d *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Int32_ty : (* %ld *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int32 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int32 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Nativeint_ty : (* %nd *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (nativeint -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ nativeint -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Int64_ty : (* %Ld *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (int64 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ int64 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Float_ty : (* %f *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (float -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ float -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Bool_ty : (* %B *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (bool -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ bool -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Format_arg_ty : (* %{...%} *)
+ ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Format_subst_ty : (* %(...%) *)
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g1, 'b1, 'c1, 'j1, 'd1, 'a1) fmtty_rel *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel *
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g1, 'b1, 'c1, 'j1, 'e1, 'f1,
+ ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
+
+ (* Printf and Format specific constructors. *)
+ | Alpha_ty : (* %a *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('b1 -> 'x -> 'c1) -> 'x -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('b2 -> 'x -> 'c2) -> 'x -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+ | Theta_ty : (* %t *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ (('b1 -> 'c1) -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ ('b2 -> 'c2) -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
+
+ (* Scanf specific constructor. *)
+ | Reader_ty : (* %r *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('x -> 'a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
+ 'x -> 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
+ | Ignored_reader_ty : (* %_r *)
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
+
+ | End_of_fmtty :
+ ('f1, 'b1, 'c1, 'd1, 'd1, 'f1,
+ 'f2, 'b2, 'c2, 'd2, 'd2, 'f2) fmtty_rel
+
+(***)
+
+(* List of format elements. *)
+and ('a, 'b, 'c, 'd, 'e, 'f) fmt =
+ | Char : (* %c *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Caml_char : (* %C *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | String : (* %s *)
+ ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Caml_string : (* %S *)
+ ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Int : (* %[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Int32 : (* %l[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int32 -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Nativeint : (* %n[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, nativeint -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Int64 : (* %L[dixXuo] *)
+ int_conv * ('x, 'y) padding * ('y, int64 -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Float : (* %[feEgGF] *)
+ float_conv * ('x, 'y) padding * ('y, float -> 'a) precision *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x, 'b, 'c, 'd, 'e, 'f) fmt
+ | Bool : (* %[bB] *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (bool -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Flush : (* %! *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ | String_literal : (* abc *)
+ string * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Char_literal : (* x *)
+ char * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ | Format_arg : (* %{...%} *)
+ pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Format_subst : (* %(...%) *)
+ pad_option *
+ ('g, 'h, 'i, 'j, 'k, 'l,
+ 'g2, 'b, 'c, 'j2, 'd, 'a) fmtty_rel *
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b, 'c, 'j2, 'e, 'f) fmt
+
+ (* Printf and Format specific constructor. *)
+ | Alpha : (* %a *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('b -> 'x -> 'c) -> 'x -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Theta : (* %t *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (('b -> 'c) -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ (* Format specific constructor: *)
+ | Formatting : (* @_ *)
+ formatting * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ (* Scanf specific constructors: *)
+ | Reader : (* %r *)
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('x -> 'a, 'b, 'c, ('b -> 'x) -> 'd, 'e, 'f) fmt
+ | Scan_char_set : (* %[...] *)
+ pad_option * char_set * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (string -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Scan_get_counter : (* %[nlNL] *)
+ counter * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ (int -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
+ | Ignored_param : (* %_ *)
+ ('a, 'b, 'c, 'd, 'y, 'x) ignored * ('x, 'b, 'c, 'y, 'e, 'f) fmt ->
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt
+
+ | End_of_format :
+ ('f, 'b, 'c, 'e, 'e, 'f) fmt
+
+and ('a, 'b, 'c, 'd, 'e, 'f) ignored =
+ | Ignored_char :
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_caml_char :
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_string :
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_caml_string :
+ pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int :
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int32 :
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_nativeint :
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_int64 :
+ int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_float :
+ pad_option * prec_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_bool :
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_format_arg :
+ pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty ->
+ ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_format_subst :
+ pad_option * ('a, 'b, 'c, 'd, 'e, 'f) fmtty ->
+ ('a, 'b, 'c, 'd, 'e, 'f) ignored
+ | Ignored_reader :
+ ('a, 'b, 'c, ('b -> 'x) -> 'd, 'd, 'a) ignored
+ | Ignored_scan_char_set :
+ pad_option * char_set -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+ | Ignored_scan_get_counter :
+ counter -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
+
+and ('a, 'b, 'c, 'd, 'e, 'f) format6 =
+ Format of ('a, 'b, 'c, 'd, 'e, 'f) fmt * string
+
+val concat_fmtty :
+ ('g1, 'b1, 'c1, 'j1, 'd1, 'a1,
+ 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel ->
+ ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
+ 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
+ ('g1, 'b1, 'c1, 'j1, 'e1, 'f1,
+ 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
+
+val erase_rel :
+ ('a, 'b, 'c, 'd, 'e, 'f,
+ 'g, 'h, 'i, 'j, 'k, 'l) fmtty_rel -> ('a, 'b, 'c, 'd, 'e, 'f) fmtty
+
+val concat_fmt :
+ ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
+ ('f, 'b, 'c, 'e, 'g, 'h) fmt ->
+ ('a, 'b, 'c, 'd, 'g, 'h) fmt
diff --git a/stdlib/pervasives.ml b/stdlib/pervasives.ml
index 54bf0ad4e..8f9e423f9 100644
--- a/stdlib/pervasives.ml
+++ b/stdlib/pervasives.ml
@@ -448,613 +448,6 @@ module LargeFile =
(* Formats *)
-module CamlinternalFormatBasics = struct
-(* Type of a block used by the Format pretty-printer. *)
-type block_type =
- | Pp_hbox (* Horizontal block no line breaking *)
- | Pp_vbox (* Vertical block each break leads to a new line *)
- | Pp_hvbox (* Horizontal-vertical block: same as vbox, except if this block
- is small enough to fit on a single line *)
- | Pp_hovbox (* Horizontal or Vertical block: breaks lead to new line
- only when necessary to print the content of the block *)
- | Pp_box (* Horizontal or Indent block: breaks lead to new line
- only when necessary to print the content of the block, or
- when it leads to a new indentation of the current line *)
- | Pp_fits (* Internal usage: when a block fits on a single line *)
-
-(* Formatting element used by the Format pretty-printter. *)
-type formatting =
- | Open_box of string * block_type * int (* @[ *)
- | Close_box (* @] *)
- | Open_tag of string * string (* @{ *)
- | Close_tag (* @} *)
- | Break of string * int * int (* @, | @ | @; | @;<> *)
- | FFlush (* @? *)
- | Force_newline (* @\n *)
- | Flush_newline (* @. *)
- | Magic_size of string * int (* @<n> *)
- | Escaped_at (* @@ *)
- | Escaped_percent (* @%% *)
- | Scan_indic of char (* @X *)
-
-(***)
-
-(* Padding position. *)
-type padty =
- | Left (* Text is left justified ('-' option). *)
- | Right (* Text is right justified (no '-' option). *)
- | Zeros (* Text is right justified by zeros (see '0' option). *)
-
-(***)
-
-(* Integer conversion. *)
-type int_conv =
- | Int_d | Int_pd | Int_sd (* %d | %+d | % d *)
- | Int_i | Int_pi | Int_si (* %i | %+i | % i *)
- | Int_x | Int_Cx (* %x | %#x *)
- | Int_X | Int_CX (* %X | %#X *)
- | Int_o | Int_Co (* %o | %#o *)
- | Int_u (* %u *)
-
-(* Float conversion. *)
-type float_conv =
- | Float_f | Float_pf | Float_sf (* %f | %+f | % f *)
- | Float_e | Float_pe | Float_se (* %e | %+e | % e *)
- | Float_E | Float_pE | Float_sE (* %E | %+E | % E *)
- | Float_g | Float_pg | Float_sg (* %g | %+g | % g *)
- | Float_G | Float_pG | Float_sG (* %G | %+G | % G *)
- | Float_F (* %F *)
-
-(***)
-
-(* Char sets (see %[...]) are bitmaps implemented as 32-char strings. *)
-type char_set = string
-
-(***)
-
-(* Counter used in Scanf. *)
-type counter =
- | Line_counter (* %l *)
- | Char_counter (* %n *)
- | Token_counter (* %N, %L *)
-
-(***)
-
-(* Padding of strings and numbers. *)
-type ('a, 'b) padding =
- (* No padding (ex: "%d") *)
- | No_padding : ('a, 'a) padding
- (* Literal padding (ex: "%8d") *)
- | Lit_padding : padty * int -> ('a, 'a) padding
- (* Padding as extra argument (ex: "%*d") *)
- | Arg_padding : padty -> (int -> 'a, 'a) padding
-
-(* Some formats, such as %_d,
- only accept an optional number as padding option (no extra argument) *)
-type pad_option = int option
-
-(* Precision of floats and '0'-padding of integers. *)
-type ('a, 'b) precision =
- (* No precision (ex: "%f") *)
- | No_precision : ('a, 'a) precision
- (* Literal precision (ex: "%.3f") *)
- | Lit_precision : int -> ('a, 'a) precision
- (* Precision as extra argument (ex: "%.*f") *)
- | Arg_precision : (int -> 'a, 'a) precision
-
-(* Some formats, such as %_f,
- only accept an optional number as precision option (no extra argument) *)
-type prec_option = int option
-
-(***)
-
-(* Relational format types
-
-In the first format+gadts implementation, the type for %(..%) in the
-fmt GADT was as follows:
-
-| Format_subst : (* %(...%) *)
- pad_option * ('d1, 'q1, 'd2, 'q2) reader_nb_unifier *
- ('x, 'b, 'c, 'd1, 'q1, 'u) fmtty *
- ('u, 'b, 'c, 'q1, 'e1, 'f) fmt ->
- (('x, 'b, 'c, 'd2, 'q2, 'u) format6 -> 'x, 'b, 'c, 'd1, 'e1, 'f) fmt
-
-Notice that the 'u parameter in 'f position in the format argument
-(('x, .., 'u) format6 -> ..) is equal to the 'u parameter in 'a
-position in the format tail (('u, .., 'f) fmt). This means that the
-type of the expected format parameter depends of where the %(...%)
-are in the format string:
-
- # Printf.printf "%(%)";;
- - : (unit, out_channel, unit, '_a, '_a, unit)
- CamlinternalFormatBasics.format6 -> unit
- = <fun>
- # Printf.printf "%(%)%d";;
- - : (int -> unit, out_channel, unit, '_a, '_a, int -> unit)
- CamlinternalFormatBasics.format6 -> int -> unit
- = <fun>
-
-On the contrary, the legacy typer gives a clever type that does not
-depend on the position of %(..%) in the format string. For example,
-%(%) will have the polymorphic type ('a, 'b, 'c, 'd, 'd, 'a): it can
-be concatenated to any format type, and only enforces the constraint
-that its 'a and 'f parameters are equal (no format arguments) and 'd
-and 'e are equal (no reader argument).
-
-The weakening of this parameter type in the GADT version broke user
-code (in fact it essentially made %(...%) unusable except at the last
-position of a format). In particular, the following would not work
-anymore:
-
- fun sep ->
- Format.printf "foo%(%)bar%(%)baz" sep sep
-
-As the type-checker would require two *incompatible* types for the %(%)
-in different positions.
-
-The solution to regain a general type for %(..%) is to generalize this
-technique, not only on the 'd, 'e parameters, but on all six
-parameters of a format: we introduce a "relational" type
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
-whose values are proofs that ('a1, .., 'f1) and ('a2, .., 'f2) morally
-correspond to the same format type: 'a1 is obtained from 'f1,'b1,'c1
-in the exact same way that 'a2 is obtained from 'f2,'b2,'c2, etc.
-
-For example, the relation between two format types beginning with a Char
-parameter is as follows:
-
-| Char_ty : (* %c *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (char -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- char -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
-
-In the general case, the term structure of fmtty_rel is (almost¹)
-isomorphic to the fmtty of the previous implementation: every
-constructor is re-read with a binary, relational type, instead of the
-previous unary typing. fmtty can then be re-defined as the diagonal of
-fmtty_rel:
-
- type ('a, 'b, 'c, 'd, 'e, 'f) fmtty =
- ('a, 'b, 'c, 'd, 'e, 'f,
- 'a, 'b, 'c, 'd, 'e, 'f) fmtty_rel
-
-Once we have this fmtty_rel type in place, we can give the more
-general type to %(...%):
-
-| Format_subst : (* %(...%) *)
- pad_option *
- ('g, 'h, 'i, 'j, 'k, 'l,
- 'g2, 'b, 'c, 'j2, 'd, 'a) fmtty_rel *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b, 'c, 'j2, 'e, 'f) fmt
-
-We accept any format (('g, 'h, 'i, 'j, 'k, 'l) format6) (this is
-completely unrelated to the type of the current format), but also
-require a proof that this format is in relation to another format that
-is concatenable to the format tail. When executing a %(...%) format
-(in camlinternalFormat.ml:make_printf or scanf.ml:make_scanf), we
-transtype the format along this relation using the 'recast' function
-to transpose between related format types.
-
- val recast :
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1) fmt
- -> ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- -> ('a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmt
-
-NOTE ¹: the typing of Format_subst_ty requires not one format type, but
-two, one to establish the link between the format argument and the
-first six parameters, and the other for the link between the format
-argumant and the last six parameters.
-
-| Format_subst_ty : (* %(...%) *)
- ('g, 'h, 'i, 'j, 'k, 'l,
- 'g1, 'b1, 'c1, 'j1, 'd1, 'a1) fmtty_rel *
- ('g, 'h, 'i, 'j, 'k, 'l,
- 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel *
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g1, 'b1, 'c1, 'j1, 'e1, 'f1,
- ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
-
-When we generate a format AST, we generate exactly the same witness
-for both relations, and the witness-conversion functions in
-camlinternalFormat do rely on this invariant. For example, the
-function that proves that the relation is transitive
-
- val trans :
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- -> ('a2, 'b2, 'c2, 'd2, 'e2, 'f2,
- 'a3, 'b3, 'c3, 'd3, 'e3, 'f3) fmtty_rel
- -> ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a3, 'b3, 'c3, 'd3, 'e3, 'f3) fmtty_rel
-
-does assume that the two input have exactly the same term structure
-(and is only every used for argument witnesses of the
-Format_subst_ty constructor).
-*)
-
-(* List of format type elements. *)
-(* In particular used to represent %(...%) and %{...%} contents. *)
-type ('a, 'b, 'c, 'd, 'e, 'f) fmtty =
- ('a, 'b, 'c, 'd, 'e, 'f,
- 'a, 'b, 'c, 'd, 'e, 'f) fmtty_rel
-and ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel =
- | Char_ty : (* %c *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (char -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- char -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | String_ty : (* %s *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (string -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- string -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Int_ty : (* %d *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (int -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- int -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Int32_ty : (* %ld *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (int32 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- int32 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Nativeint_ty : (* %nd *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (nativeint -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- nativeint -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Int64_ty : (* %Ld *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (int64 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- int64 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Float_ty : (* %f *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (float -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- float -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Bool_ty : (* %B *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (bool -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- bool -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
-
- | Format_arg_ty : (* %{...%} *)
- ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Format_subst_ty : (* %(...%) *)
- ('g, 'h, 'i, 'j, 'k, 'l,
- 'g1, 'b1, 'c1, 'j1, 'd1, 'a1) fmtty_rel *
- ('g, 'h, 'i, 'j, 'k, 'l,
- 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel *
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g1, 'b1, 'c1, 'j1, 'e1, 'f1,
- ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
-
- (* Printf and Format specific constructors. *)
- | Alpha_ty : (* %a *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (('b1 -> 'x -> 'c1) -> 'x -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- ('b2 -> 'x -> 'c2) -> 'x -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Theta_ty : (* %t *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (('b1 -> 'c1) -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- ('b2 -> 'c2) -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
-
- (* Scanf specific constructor. *)
- | Reader_ty : (* %r *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- ('x -> 'a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
- 'x -> 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
- | Ignored_reader_ty : (* %_r *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- ('a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
-
- | End_of_fmtty :
- ('f1, 'b1, 'c1, 'd1, 'd1, 'f1,
- 'f2, 'b2, 'c2, 'd2, 'd2, 'f2) fmtty_rel
-
-(***)
-
-(* List of format elements. *)
-and ('a, 'b, 'c, 'd, 'e, 'f) fmt =
- | Char : (* %c *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Caml_char : (* %C *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | String : (* %s *)
- ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Caml_string : (* %S *)
- ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Int : (* %[dixXuo] *)
- int_conv * ('x, 'y) padding * ('y, int -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Int32 : (* %l[dixXuo] *)
- int_conv * ('x, 'y) padding * ('y, int32 -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Nativeint : (* %n[dixXuo] *)
- int_conv * ('x, 'y) padding * ('y, nativeint -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Int64 : (* %L[dixXuo] *)
- int_conv * ('x, 'y) padding * ('y, int64 -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Float : (* %[feEgGF] *)
- float_conv * ('x, 'y) padding * ('y, float -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Bool : (* %[bB] *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (bool -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Flush : (* %! *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
-
- | String_literal : (* abc *)
- string * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
- | Char_literal : (* x *)
- char * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
-
- | Format_arg : (* %{...%} *)
- pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Format_subst : (* %(...%) *)
- pad_option *
- ('g, 'h, 'i, 'j, 'k, 'l,
- 'g2, 'b, 'c, 'j2, 'd, 'a) fmtty_rel *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b, 'c, 'j2, 'e, 'f) fmt
-
- (* Printf and Format specific constructor. *)
- | Alpha : (* %a *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (('b -> 'x -> 'c) -> 'x -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Theta : (* %t *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (('b -> 'c) -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
-
- (* Format specific constructor: *)
- | Formatting : (* @_ *)
- formatting * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
-
- (* Scanf specific constructors: *)
- | Reader : (* %r *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x -> 'a, 'b, 'c, ('b -> 'x) -> 'd, 'e, 'f) fmt
- | Scan_char_set : (* %[...] *)
- pad_option * char_set * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (string -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Scan_get_counter : (* %[nlNL] *)
- counter * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (int -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Ignored_param : (* %_ *)
- ('a, 'b, 'c, 'd, 'y, 'x) ignored * ('x, 'b, 'c, 'y, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
-
- | End_of_format :
- ('f, 'b, 'c, 'e, 'e, 'f) fmt
-
-(***)
-
-(* Type for ignored parameters (see "%_"). *)
-and ('a, 'b, 'c, 'd, 'e, 'f) ignored =
- | Ignored_char : (* %_c *)
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_caml_char : (* %_C *)
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_string : (* %_s *)
- pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_caml_string : (* %_S *)
- pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_int : (* %_d *)
- int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_int32 : (* %_ld *)
- int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_nativeint : (* %_nd *)
- int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_int64 : (* %_Ld *)
- int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_float : (* %_f *)
- pad_option * prec_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_bool : (* %_B *)
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_format_arg : (* %_{...%} *)
- pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty ->
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_format_subst : (* %_(...%) *)
- pad_option * ('a, 'b, 'c, 'd, 'e, 'f) fmtty ->
- ('a, 'b, 'c, 'd, 'e, 'f) ignored
- | Ignored_reader : (* %_r *)
- ('a, 'b, 'c, ('b -> 'x) -> 'd, 'd, 'a) ignored
- | Ignored_scan_char_set : (* %_[...] *)
- pad_option * char_set -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_scan_get_counter : (* %_[nlNL] *)
- counter -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
-
-and ('a, 'b, 'c, 'd, 'e, 'f) format6 =
- Format of ('a, 'b, 'c, 'd, 'e, 'f) fmt * string
-
-let rec erase_rel : type a b c d e f g h i j k l .
- (a, b, c, d, e, f,
- g, h, i, j, k, l) fmtty_rel -> (a, b, c, d, e, f) fmtty
-= function
- | Char_ty rest ->
- Char_ty (erase_rel rest)
- | String_ty rest ->
- String_ty (erase_rel rest)
- | Int_ty rest ->
- Int_ty (erase_rel rest)
- | Int32_ty rest ->
- Int32_ty (erase_rel rest)
- | Int64_ty rest ->
- Int64_ty (erase_rel rest)
- | Nativeint_ty rest ->
- Nativeint_ty (erase_rel rest)
- | Float_ty rest ->
- Float_ty (erase_rel rest)
- | Bool_ty rest ->
- Bool_ty (erase_rel rest)
- | Format_arg_ty (ty, rest) ->
- Format_arg_ty (ty, erase_rel rest)
- | Format_subst_ty (ty1, ty2, rest) ->
- Format_subst_ty (ty1, ty1, erase_rel rest)
- | Alpha_ty rest ->
- Alpha_ty (erase_rel rest)
- | Theta_ty rest ->
- Theta_ty (erase_rel rest)
- | Reader_ty rest ->
- Reader_ty (erase_rel rest)
- | Ignored_reader_ty rest ->
- Ignored_reader_ty (erase_rel rest)
- | End_of_fmtty -> End_of_fmtty
-
-(******************************************************************************)
- (* Format type concatenation *)
-
-(* Concatenate two format types. *)
-(* Used by:
- * reader_nb_unifier_of_fmtty to count readers in an fmtty,
- * Scanf.take_fmtty_format_readers to extract readers inside %(...%),
- * CamlinternalFormat.fmtty_of_ignored_format to extract format type. *)
-
-(*
-let rec concat_fmtty : type a b c d e f g h .
- (a, b, c, d, e, f) fmtty ->
- (f, b, c, e, g, h) fmtty ->
- (a, b, c, d, g, h) fmtty =
-*)
-let rec concat_fmtty :
- type a1 b1 c1 d1 e1 f1
- a2 b2 c2 d2 e2 f2
- g1 j1 g2 j2
- .
- (g1, b1, c1, j1, d1, a1,
- g2, b2, c2, j2, d2, a2) fmtty_rel ->
- (a1, b1, c1, d1, e1, f1,
- a2, b2, c2, d2, e2, f2) fmtty_rel ->
- (g1, b1, c1, j1, e1, f1,
- g2, b2, c2, j2, e2, f2) fmtty_rel =
-fun fmtty1 fmtty2 -> match fmtty1 with
- | Char_ty rest ->
- Char_ty (concat_fmtty rest fmtty2)
- | String_ty rest ->
- String_ty (concat_fmtty rest fmtty2)
- | Int_ty rest ->
- Int_ty (concat_fmtty rest fmtty2)
- | Int32_ty rest ->
- Int32_ty (concat_fmtty rest fmtty2)
- | Nativeint_ty rest ->
- Nativeint_ty (concat_fmtty rest fmtty2)
- | Int64_ty rest ->
- Int64_ty (concat_fmtty rest fmtty2)
- | Float_ty rest ->
- Float_ty (concat_fmtty rest fmtty2)
- | Bool_ty rest ->
- Bool_ty (concat_fmtty rest fmtty2)
- | Alpha_ty rest ->
- Alpha_ty (concat_fmtty rest fmtty2)
- | Theta_ty rest ->
- Theta_ty (concat_fmtty rest fmtty2)
- | Reader_ty rest ->
- Reader_ty (concat_fmtty rest fmtty2)
- | Ignored_reader_ty rest ->
- Ignored_reader_ty (concat_fmtty rest fmtty2)
- | Format_arg_ty (ty, rest) ->
- Format_arg_ty (ty, concat_fmtty rest fmtty2)
- | Format_subst_ty (ty1, ty2, rest) ->
- Format_subst_ty (ty1, ty2, concat_fmtty rest fmtty2)
- | End_of_fmtty -> fmtty2
-
-(******************************************************************************)
- (* Format concatenation *)
-
-(* Concatenate two formats. *)
-let rec concat_fmt : type a b c d e f g h .
- (a, b, c, d, e, f) fmt ->
- (f, b, c, e, g, h) fmt ->
- (a, b, c, d, g, h) fmt =
-fun fmt1 fmt2 -> match fmt1 with
- | String (pad, rest) ->
- String (pad, concat_fmt rest fmt2)
- | Caml_string (pad, rest) ->
- Caml_string (pad, concat_fmt rest fmt2)
-
- | Int (iconv, pad, prec, rest) ->
- Int (iconv, pad, prec, concat_fmt rest fmt2)
- | Int32 (iconv, pad, prec, rest) ->
- Int32 (iconv, pad, prec, concat_fmt rest fmt2)
- | Nativeint (iconv, pad, prec, rest) ->
- Nativeint (iconv, pad, prec, concat_fmt rest fmt2)
- | Int64 (iconv, pad, prec, rest) ->
- Int64 (iconv, pad, prec, concat_fmt rest fmt2)
- | Float (fconv, pad, prec, rest) ->
- Float (fconv, pad, prec, concat_fmt rest fmt2)
-
- | Char (rest) ->
- Char (concat_fmt rest fmt2)
- | Caml_char rest ->
- Caml_char (concat_fmt rest fmt2)
- | Bool rest ->
- Bool (concat_fmt rest fmt2)
- | Alpha rest ->
- Alpha (concat_fmt rest fmt2)
- | Theta rest ->
- Theta (concat_fmt rest fmt2)
- | Reader rest ->
- Reader (concat_fmt rest fmt2)
- | Flush rest ->
- Flush (concat_fmt rest fmt2)
-
- | String_literal (str, rest) ->
- String_literal (str, concat_fmt rest fmt2)
- | Char_literal (chr, rest) ->
- Char_literal (chr, concat_fmt rest fmt2)
-
- | Format_arg (pad, fmtty, rest) ->
- Format_arg (pad, fmtty, concat_fmt rest fmt2)
- | Format_subst (pad, fmtty, rest) ->
- Format_subst (pad, fmtty, concat_fmt rest fmt2)
-
- | Scan_char_set (width_opt, char_set, rest) ->
- Scan_char_set (width_opt, char_set, concat_fmt rest fmt2)
- | Scan_get_counter (counter, rest) ->
- Scan_get_counter (counter, concat_fmt rest fmt2)
- | Ignored_param (ign, rest) ->
- Ignored_param (ign, concat_fmt rest fmt2)
-
- | Formatting (fmting, rest) ->
- Formatting (fmting, concat_fmt rest fmt2)
-
- | End_of_format ->
- fmt2
-end
-
type ('a, 'b, 'c, 'd, 'e, 'f) format6
= ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.format6
= Format of ('a, 'b, 'c, 'd, 'e, 'f) CamlinternalFormatBasics.fmt
diff --git a/stdlib/pervasives.mli b/stdlib/pervasives.mli
index e866e2243..77cb1e92c 100644
--- a/stdlib/pervasives.mli
+++ b/stdlib/pervasives.mli
@@ -966,289 +966,6 @@ external decr : int ref -> unit = "%decr"
{!Printf} and {!Format}.
*)
-module CamlinternalFormatBasics : sig
- (* No comments, OCaml stdlib internal use only. *)
-
- type block_type = Pp_hbox | Pp_vbox | Pp_hvbox | Pp_hovbox | Pp_box | Pp_fits
-
- type formatting =
- | Open_box of string * block_type * int
- | Close_box
- | Open_tag of string * string
- | Close_tag
- | Break of string * int * int
- | FFlush
- | Force_newline
- | Flush_newline
- | Magic_size of string * int
- | Escaped_at
- | Escaped_percent
- | Scan_indic of char
-
- type padty = Left | Right | Zeros
-
- type int_conv =
- | Int_d | Int_pd | Int_sd | Int_i | Int_pi | Int_si
- | Int_x | Int_Cx | Int_X | Int_CX | Int_o | Int_Co | Int_u
-
- type float_conv =
- | Float_f | Float_pf | Float_sf | Float_e | Float_pe | Float_se
- | Float_E | Float_pE | Float_sE | Float_g | Float_pg | Float_sg
- | Float_G | Float_pG | Float_sG | Float_F
-
- type char_set = string
-
- type counter = Line_counter | Char_counter | Token_counter
-
- type ('a, 'b) padding =
- | No_padding : ('a, 'a) padding
- | Lit_padding : padty * int -> ('a, 'a) padding
- | Arg_padding : padty -> (int -> 'a, 'a) padding
-
- type pad_option = int option
-
- type ('a, 'b) precision =
- | No_precision : ('a, 'a) precision
- | Lit_precision : int -> ('a, 'a) precision
- | Arg_precision : (int -> 'a, 'a) precision
-
- type prec_option = int option
-
-type ('a, 'b, 'c, 'd, 'e, 'f) fmtty =
- ('a, 'b, 'c, 'd, 'e, 'f,
- 'a, 'b, 'c, 'd, 'e, 'f) fmtty_rel
-and ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel =
- | Char_ty : (* %c *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (char -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- char -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | String_ty : (* %s *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (string -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- string -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Int_ty : (* %d *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (int -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- int -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Int32_ty : (* %ld *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (int32 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- int32 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Nativeint_ty : (* %nd *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (nativeint -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- nativeint -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Int64_ty : (* %Ld *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (int64 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- int64 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Float_ty : (* %f *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (float -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- float -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Bool_ty : (* %B *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (bool -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- bool -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Format_arg_ty : (* %{...%} *)
- ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Format_subst_ty : (* %(...%) *)
- ('g, 'h, 'i, 'j, 'k, 'l,
- 'g1, 'b1, 'c1, 'j1, 'd1, 'a1) fmtty_rel *
- ('g, 'h, 'i, 'j, 'k, 'l,
- 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel *
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g1, 'b1, 'c1, 'j1, 'e1, 'f1,
- ('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
-
- (* Printf and Format specific constructors. *)
- | Alpha_ty : (* %a *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (('b1 -> 'x -> 'c1) -> 'x -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- ('b2 -> 'x -> 'c2) -> 'x -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
- | Theta_ty : (* %t *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- (('b1 -> 'c1) -> 'a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- ('b2 -> 'c2) -> 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel
-
- (* Scanf specific constructor. *)
- | Reader_ty : (* %r *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- ('x -> 'a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
- 'x -> 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
- | Ignored_reader_ty : (* %_r *)
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- ('a1, 'b1, 'c1, ('b1 -> 'x) -> 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, ('b2 -> 'x) -> 'd2, 'e2, 'f2) fmtty_rel
-
- | End_of_fmtty :
- ('f1, 'b1, 'c1, 'd1, 'd1, 'f1,
- 'f2, 'b2, 'c2, 'd2, 'd2, 'f2) fmtty_rel
-
-(***)
-
-(* List of format elements. *)
-and ('a, 'b, 'c, 'd, 'e, 'f) fmt =
- | Char : (* %c *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Caml_char : (* %C *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (char -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | String : (* %s *)
- ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Caml_string : (* %S *)
- ('x, string -> 'a) padding * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Int : (* %[dixXuo] *)
- int_conv * ('x, 'y) padding * ('y, int -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Int32 : (* %l[dixXuo] *)
- int_conv * ('x, 'y) padding * ('y, int32 -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Nativeint : (* %n[dixXuo] *)
- int_conv * ('x, 'y) padding * ('y, nativeint -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Int64 : (* %L[dixXuo] *)
- int_conv * ('x, 'y) padding * ('y, int64 -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Float : (* %[feEgGF] *)
- float_conv * ('x, 'y) padding * ('y, float -> 'a) precision *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x, 'b, 'c, 'd, 'e, 'f) fmt
- | Bool : (* %[bB] *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (bool -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Flush : (* %! *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
-
- | String_literal : (* abc *)
- string * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
- | Char_literal : (* x *)
- char * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
-
- | Format_arg : (* %{...%} *)
- pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Format_subst : (* %(...%) *)
- pad_option *
- ('g, 'h, 'i, 'j, 'k, 'l,
- 'g2, 'b, 'c, 'j2, 'd, 'a) fmtty_rel *
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (('g, 'h, 'i, 'j, 'k, 'l) format6 -> 'g2, 'b, 'c, 'j2, 'e, 'f) fmt
-
- (* Printf and Format specific constructor. *)
- | Alpha : (* %a *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (('b -> 'x -> 'c) -> 'x -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Theta : (* %t *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (('b -> 'c) -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
-
- (* Format specific constructor: *)
- | Formatting : (* @_ *)
- formatting * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
-
- (* Scanf specific constructors: *)
- | Reader : (* %r *)
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('x -> 'a, 'b, 'c, ('b -> 'x) -> 'd, 'e, 'f) fmt
- | Scan_char_set : (* %[...] *)
- pad_option * char_set * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (string -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Scan_get_counter : (* %[nlNL] *)
- counter * ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- (int -> 'a, 'b, 'c, 'd, 'e, 'f) fmt
- | Ignored_param : (* %_ *)
- ('a, 'b, 'c, 'd, 'y, 'x) ignored * ('x, 'b, 'c, 'y, 'e, 'f) fmt ->
- ('a, 'b, 'c, 'd, 'e, 'f) fmt
-
- | End_of_format :
- ('f, 'b, 'c, 'e, 'e, 'f) fmt
-
- and ('a, 'b, 'c, 'd, 'e, 'f) ignored =
- | Ignored_char :
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_caml_char :
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_string :
- pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_caml_string :
- pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_int :
- int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_int32 :
- int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_nativeint :
- int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_int64 :
- int_conv * pad_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_float :
- pad_option * prec_option -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_bool :
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_format_arg :
- pad_option * ('g, 'h, 'i, 'j, 'k, 'l) fmtty ->
- ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_format_subst :
- pad_option * ('a, 'b, 'c, 'd, 'e, 'f) fmtty ->
- ('a, 'b, 'c, 'd, 'e, 'f) ignored
- | Ignored_reader :
- ('a, 'b, 'c, ('b -> 'x) -> 'd, 'd, 'a) ignored
- | Ignored_scan_char_set :
- pad_option * char_set -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
- | Ignored_scan_get_counter :
- counter -> ('a, 'b, 'c, 'd, 'd, 'a) ignored
-
- and ('a, 'b, 'c, 'd, 'e, 'f) format6 =
- Format of ('a, 'b, 'c, 'd, 'e, 'f) fmt * string
-
- val concat_fmtty :
- ('g1, 'b1, 'c1, 'j1, 'd1, 'a1,
- 'g2, 'b2, 'c2, 'j2, 'd2, 'a2) fmtty_rel ->
- ('a1, 'b1, 'c1, 'd1, 'e1, 'f1,
- 'a2, 'b2, 'c2, 'd2, 'e2, 'f2) fmtty_rel ->
- ('g1, 'b1, 'c1, 'j1, 'e1, 'f1,
- 'g2, 'b2, 'c2, 'j2, 'e2, 'f2) fmtty_rel
-
- val erase_rel :
- ('a, 'b, 'c, 'd, 'e, 'f,
- 'g, 'h, 'i, 'j, 'k, 'l) fmtty_rel -> ('a, 'b, 'c, 'd, 'e, 'f) fmtty
-
- val concat_fmt :
- ('a, 'b, 'c, 'd, 'e, 'f) fmt ->
- ('f, 'b, 'c, 'e, 'g, 'h) fmt ->
- ('a, 'b, 'c, 'd, 'g, 'h) fmt
-end
-
(** Format strings have a general and highly polymorphic type
[('a, 'b, 'c, 'd, 'e, 'f) format6].
The two simplified types, [format] and [format4] below are