module Delimited_overloading:(submodule ofsig..end
Pa_do) Syntax extension module to enable easy local overloading of operators and functions. The principle is
simple: expressions like X1.X2...Xk.(expr) are automatically
transformed, substituting constants, operators, and functions in
expr and possibly optimizing the resulting expression. For
example, you can write Float.(1 + x / 3) and it will be just as
if you wrote 1.0 +. x /. 3.0.
This library comes with overloadings of arithmetic and comparison
operators for all standard OCaml numeric types, namely Int,
Float, Complex, Int32, Int64, Nativeint, Num,
Big_int, and Ratio (the latter three are in Pa_do_nums
since they require to load nums.cma for compile time checks).
Where applicable the functions lsl, lsr, land, lor,
succ, pred, floor, max, min, abs, truncate,... are
also overloaded.
There are two ways of using this syntax extension to define your own overloadings.
1. Creating a camlp4 syntax module
Here you create a file, say my_syntax.ml, and use the API below to define your overloadings. This is the recommended and more powerful way.
2. Using the concrete syntax
From time to time, you'll find that you need a quick way to
overload operators for a module you just defined. In this case,
you can the concrete syntax which allows simple overloading to be
defined. Given a module longident X (i.e. X has the form
X1.X2...Xk for some modules X1, X2,..., Xk), you can use
OVERLOAD X (op1 -> f1; op2 -> f2; ...)
to mean that op1 should be replaced by X.f1, etc. Note that
the functions f1, f2,... will be automatically qualified by
the module X. For example, if you set OVERLOAD X((+) -> add;
succ -> succ), then the expression X.(x + succ y) will be
transformed into A.add x (X.succ y). The shortcut OVERLOAD X
(f) means OVERLOAD X (f -> f). You can overload literal values
using
OVERLOAD_INT X(f) (* the argument of f is an int *)
OVERLOAD_FLOAT X(f) (* the argument of f is a float *)
OVERLOAD_INT32 X(f) (* the argument of f is an int32 *)
OVERLOAD_INT64 X(f) (* the argument of f is an int64 *)
OVERLOAD_NATIVEINT X(f) (* the argument of f is a nativeint *)
OVERLOAD_STRING X(f) (* the argument of f is a string *)
OVERLOAD_POLY_VAR X(f) (* the argument of f is a string *)
which will replace any constant x with f x. The meaning of
common constructions can also be changed:
OVERLOAD_ARRAY_GET X(f) (* [a.(i)] is transformed into [X.f a i] *)
OVERLOAD_ARRAY_SET X(f) (* [a.(i) <- x] is transformed into [X.f a i x] *)
OVERLOAD_BIGARRAY_GET X(f) (* [a.{i1,...,iN})] is transformed into
[X.f a [| i1;...; iN |]] *)
OVERLOAD_BIGARRAY_SET X(f) (* [a.{i1,...,iN} <- x] is transformed into
[X.f a [| i1;...; iN |] x] *)
OVERLOAD_STRING_GET X(f) (* [a.[i]] is transformed into [X.f a i] *)
OVERLOAD_STRING_SET X(f) (* [a.[i] <- x] is transformed into [X.f a i x] *)
OVERLOAD_ASSIGN_REF X(f) (* [a := x] is transformed into [X.f a x] *)
As a convenience, you can use OVERLOAD_ARITHMETIC X to overload
the usual arithmetic operators (see
Delimited_overloading.std_arithmetic) and OVERLOAD_COMPARISON
X(cmp) to interpret comparison operators using the compare
function cmp (see Delimited_overloading.comparison for more
details). As it is a common case, you can use the shortcut
OVERLOAD_COMPARISON X for OVERLOAD_COMPARISON X(compare). You
can add to X the overloadings defined in another module
longident, say Y, by doing OVERLOAD X inherit Y. Finally, you
can use
OVERLOAD_OPENIN X
(resp. OVERLOAD_OPENIN X(false)) to enable (resp. disable) the
opening of the module M in e for an expression like M.(e).
In all the above directives X can have the special value
DEFAULT. Setting overloadings for DEFAULT will apply these
overloadings to all modules for which no specific overloadings
have been set.
Remark: Saving constant expressions to avoid evaluating them
more than once (see Delimited_overloading.int) is not enabled
for the concrete syntax. This is because usually the module to be
overloaded is usually defined in the same source file and
therefore will not be known by the bindings put at the beginning
of the source file.
Author(s): Dany Maslowski, Julie De Pril, Christophe Troestler
Version: 0.7.1
type t
typemodule_longident =Macro.Module_longident.t
A.B.C.typereloc_expr =module_longident ->
Camlp4.PreCast.Syntax.Ast.Loc.t -> Camlp4.PreCast.Syntax.Ast.expr
The purpose is as follows. Suppose we want to overload "+"
with add. add must be qualified with the module to which it
belongs. However we do not know yet what that module will be
because we want to use this overloading with several modules.
The same goes for the location: for correct error reporting, the
location of the subtituted expression must be the location of
"+" wich is currently unknown. Thus the right way to declare
the overloading of + is using fun m _loc -> qualify_lid add m
_loc, where qualify_lid is explained below.
exception Invalid_identifier of string
Invalid_identifier m is raised to indicate that the
string m is not a valid identifier (lowercase or operator).val empty : tval concat : t -> t -> tconcat t1 t2 "concatenates" the overloadings in t1 and t2.
If a constant, string, identifier,... has been overloaded in
t1 and in t2, then the overloading of t2 is the one
present in the result of concat.val qualify_lid : string -> reloc_exprqualify_lid lid m _loc returns the expression of the operator
or function name lid qualified with the module longident m.
See reloc_expr for a use case of this function.val int : t ->
?cache:bool ->
(int -> reloc_expr) -> tint t f return the same "set of overloadings" that t with the new
function f that specifies how integer constants are overloaded for t.cache : if true (the default), for any literal i, binds
the expression transforming i at the beginning of the source
file so it is only evaluated once. The overloaded module must
therefore be know at for the whole source (this is generally the
case for a library).val float : t ->
?cache:bool ->
(float -> reloc_expr) -> tfloat t f return the same "set of overloadings" that t with the new
function f that specifies how float constants are overloaded for t.cache : see Delimited_overloading.int.val nativeint : t ->
?cache:bool ->
(nativeint -> reloc_expr) -> tnativeint t f return the "set of overloadings" t augmented with the
new function f that specifies how nativeint constants are overloaded
for t.cache : see Delimited_overloading.int.val int32 : t ->
?cache:bool ->
(int32 -> reloc_expr) -> tint32 t f return the "set of overloadings" t augmented with the new
function f that specifies how int32 constants are overloaded for t.cache : see Delimited_overloading.int.val int64 : t ->
?cache:bool ->
(int64 -> reloc_expr) -> tint64 t f return the "set of overloadings" t augmented with the new
function f that specifies how int64 constants are overloaded for t.cache : see Delimited_overloading.int.val string : t ->
?cache:bool ->
check:(string -> 'a) ->
?to_type:(string -> string) ->
(string -> reloc_expr) -> tstring t f return the "set of overloadings" t augmented with the new
function f that specifies how string constants are overloaded for t.cache : see Delimited_overloading.int.check : a function that checks that the string represent a
valid value. If it does not, it is expected that check raise
an exception (which one is unimportant).to_type : Allows to customize the error message in case
check fails. to_type receive the module name and is
expected to return a string characterizing the type of the
expected value. Default: identity.val poly_var : t ->
?cache:bool ->
check:(string -> 'a) ->
?to_type:(string -> string) ->
(string -> reloc_expr) -> tpoly_var t f return the "set of overloadings" t augmented with the new
function f that specifies how the lowercase polymorphic variants are
overloaded for t. The string argument of f is the name of the
polymorphic variant (for example abc is the name of `abc).cache : see Delimited_overloading.int.val list : t ->
(Camlp4.PreCast.Syntax.Ast.expr list -> reloc_expr) ->
tlist t f return the "set of overloadings" t augmented with the new
function f that specifies how list constants are overloaded for t.val array : t ->
(Camlp4.PreCast.Syntax.Ast.expr list -> reloc_expr) ->
tarray t f return the "set of overloadings" t augmented with the new
function f that specifies how array constants are overloaded for t.
Note that Ast.exSem_of_list may be useful to group the expressions into
a single one.val array_get : t ->
(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr -> reloc_expr) ->
tarray_get t f return the "set of overloadings" t augmented with the
new function f that specifies how the construction a.(i) is overloaded
for t. Expressions like a.(i), where a and i are expressions,
will be transformed into f a i _loc where _loc is the location of
a.(i).val array_set : t ->
(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr -> reloc_expr) ->
tarray_set t f return the "set of overloadings" t augmented with the
new function f that specifies how the construction a.(i) <- x is
overloaded for t. Expressions like a.(i) <- x, where a, i, and
x are expressions, will be transformed into f a i x _loc where _loc
is the location of a.(i) <- x.val string_get : t ->
(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr -> reloc_expr) ->
tarray_get but for a.[i].val string_set : t ->
(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr -> reloc_expr) ->
tarray_set but for a.[i] <- x.val bigarray_get : t ->
(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr list -> reloc_expr) ->
tarray_get but for a.{i1,...,iK}.val bigarray_set : t ->
(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr list ->
Camlp4.PreCast.Syntax.Ast.expr -> reloc_expr) ->
tarray_set but for a.{i1,...,iK} <- x.val assign : t ->
(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr -> reloc_expr) ->
tassign t f return the "set of overloadings" t augmented with the new
function f that specifies how the assignment is overloaded for t.
More precisely, expressions a <- x will be replaced by f a x _loc
where _loc is the location of a <- x.val assign_ref : t ->
(Camlp4.PreCast.Syntax.Ast.expr ->
Camlp4.PreCast.Syntax.Ast.expr -> reloc_expr) ->
tassign t f return the "set of overloadings" t augmented with the new
function f that specifies how the reference assignment is overloaded
for t. More precisely, expressions a := x will be replaced by
f a x _loc where _loc is the location of a := x.val lid : t ->
?cache:bool ->
string -> reloc_expr -> tlid t op e return the set of overloadings t augmented with
the transformation of the identifier op in the relocatable
expression e.cache : if false, camlp4 will just replace op with the
expression a. If true, camlp4 will be bind the expression
e to an identifier and use that identifier for all occurrences
of e (this is interesting if e is a complicated function for
example). Default: true as a very small benefit can be seen
on Int32 and Int64 benchmarks.val lid_subst : t -> (string * string) list -> tlid_subst t ov return the set of overloadings t augmented
with the transformations of the identifier op in the
identifier op' for all (op, op') in the list ov. The
identifiers op' will be qualified by the module to which the
result is linked. In other words, if you set let t' =
lid_subst t ["+", "add"] and t' is linked with the module
longident M, then M.(a + b) will be transformed into M.add
a b.val std_arithmetic : t -> tstd_arithmetic t is just a shortcut for lid_subst t
[("+","add"); ("-","sub"); ("~-", "neg"); ("*","mul"); ("/","div")]val comparison : ?cache:bool ->
?cmp:string -> t -> tcomparison ?cmp t return the set of overloadings t augmented
with the transformations for comparison operators =, <>,
<, >, <=, and >= using the function name cmp to
overload them. In other words, the expression M.(a = b) will
be substituted by M.cmp a b = 0 (where the last equality is
the standard one on integers), M.(a < b) will be transformed
into M.cmp a b < 0, etc.
Associated min and max functions are also defined.
cache : whether to cache the comparison functions built
from cmp. It is generally a good idea to do so
(e.g. speed-wise).cmp : the name of the comparison function to use. It will
be automatically qualified by the module to which the result is
linked. Default: compare.val lid_remove : t -> string list -> tlid_remove t l return the set of overloadings t with all
overloadings for a lowercase identifier or an operator in the
list l removed.type transf
val self : transf ->
Camlp4.PreCast.Syntax.Ast.expr ->
module_longident -> Camlp4.PreCast.Syntax.Ast.exprself tr m e transforms e with the complete transformation
(considered complete when using apply). The localisation of
the final expression is the one of e.val super : transf ->
Camlp4.PreCast.Syntax.Ast.expr ->
module_longident -> Camlp4.PreCast.Syntax.Ast.exprsuper tr is the previous
transformation that the new one may override.val expr : t ->
(transf ->
Camlp4.PreCast.Syntax.Ast.expr ->
module_longident -> Camlp4.PreCast.Syntax.Ast.expr) ->
tconstants t f returns a new set of overloadings which executes
the transformation f first. The location of f tr e m should
be the same as e; use the function Ast.loc_of_expr to
retrieve the location from e. A typical function f is as
follows:
let f tr e m =
let _loc = Ast.loc_of_expr e in
match e with
| ... -> ...
| ...
| _ -> super tr e m
val openin : ?remove:bool -> t -> t~remove:true) the opening of
the module M for the expression e when using M.(e).val apply : t ->
module_longident ->
Camlp4.PreCast.Syntax.Ast.expr -> Camlp4.PreCast.Syntax.Ast.exprapply t m e apply the overloadings in t to the expression
e. The overloadings will be resolved for sub-expressions e'
of e appearing in e as M.(e') where M is the module name
contained in m.val associate : t -> string -> unitassociate_t t m links the "set of overloadings" t to the
module longident m.Invalid_module_longident if m does not have the form of
a module longident.module Default:sig..end
module Suspend:sig..end
val new_lid : unit -> stringnew_lid() returns the name of a new lowercase identifier.val overloaded : stringval suspended : string