package ppx_optcomp
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=a62010eaf74035ee48ef2095da464f16fb6a087948a6c9d69dd1551c4836c64b
Description
Part of the Jane Street's PPX rewriters collection.
Published: 23 May 2024
README
ppx_optcomp - Optional compilation for OCaml
ppx_optcomp stands for Optional Compilation. It is a tool used to handle optional compilations of pieces of code depending of the word size, the version of the compiler, ...
The syntax is based on OCaml item extension nodes, with keywords similar to cpp.
[%%if ocaml_version < (4, 02, 0)]
let x = 1
[%%else]
let y = 2
[%%endif]
Syntax
ppx_optcomp is implemented using ppx_driver and operates on ocaml AST. This means that whole file needs to be grammatically correct ocaml.
The general syntax is:
[%%keyword expression]
Most of the statements are only supported on the toplevel. See grammar description for detailed information where [%% ]
directives may be placed.
Note in particular that the item extensions cannot be placed inside an expression, and this would result in syntax error.
(* SYNTAX ERROR: let x = [%%if defined(abc) ] 1 [%%else] 2 [%%endif] *)
Additional syntax is provided for optional type variant declaration, as in
type t =
| FOO
| BAR [@if ocaml_version < (4, 02, 0)]
Directives
Defining variables
[%%define
identifier expression]
[%%undef
identifier]
We also allow: [%%define
identifier]
. This will define identifier to ()
. The undefined identifiers are not valid in subsequent expressions, but for expression defined(
identifier)
, which evaluates to false.
The scope of identifiers follows the same scoping rules as OCaml variables. For instance:
(* [x] is undefined *)
[%%define x 0]
(* [x] is bound to [0] *)
module A = struct
(* [x] is bound to [0] *)
[%%define x 42]
(* [x] is bound to [42] *)
end
(* [x] is bound to [0] *)
Conditionals
The following directives are available for conditional compilations:
[%%if
expression]
[%%elif
expression]
[%%else]
[%%endif]
[@if
expression]
In all cases expression must be an expression that evaluates to a boolean value. Ppx_optcomp will fail if it is not the case.
Pseudo-function defined(
identifier)
may be then used in expressions to check whether a given identifier has been defined. Note that identifiers that were not defined or undefined beforehand are assumed to be a typo, and therefore are rejected, with a notable exception of
[%%ifndef FOO]
[%%define FOO]
which is allowed even if FOO
was not seen before.
The last form may be used only in type-variant definitions and pattern matching, following constructors which are to be optional. If you need a few constructors under the same condition, you need to copy the directive multiple times, sorry.
type t =
| A of int
| B of int * int [@if ocaml >= 4.04]
...
match (v: t) with
| A x -> something x
| B (y,z) [@if ocaml >= 4.04] -> something' y z
Warnings and errors
[%%warning _string_]
will cause the pre-processor to print a message on stderr.
[%%error _string_]
will cause the pre-processor to fail with the following error message.
Note that in both cases expression can be an arbitrary expression.
Imports
Ppx_optcomp allows one to import another file using:
[%%import
filename]
where filename is a string constant. Filenames to import are resolved as follow:
if filename is relative, i.e. doesn't start with
/
, it is considered as relative to the directory of the file being parsedif filename is absolute, i.e. starts with
/
, it is used as is
Only optcomp directives are allowed in the imported files. The intended use is including some configuration variables at the beginning of a file:
[%%import "config.mlh"]
If imported file's extension is .h
, an alternate C-like syntax is expected in the file. This is to allow importing both from C and OCaml single configuration file like:
#ifndef CONFIG_H
#define CONFIG_H
#define FOO
#undef BAR
#define BAZ 3*3 + 3
#endif
Expressions and patterns
ppx_optcomp supports a subset of OCaml expressions and patterns:
literals: integers, characters and strings
tuples
true
andfalse
let-bindings
pattern matching
And it provides the following functions:
comparison operators:
=
,<
, ...boolean operators:
||
,&&
,not
, ...arithmetic operators:
+
,-
,*
,/
min
andmax
fst
andsnd
conversion functions:
to_int
,to_string
,to_char
,to_bool
defined
,not_defined
: check whether a variable is definedshow
: act as identity, but pretty-print a value to stderr
Dependencies (5)
Dev Dependencies
None
Used by (24)
-
accessor_core
>= "v0.17.0"
-
async_ssl
>= "v0.17.0"
-
async_unix
>= "v0.17.0"
-
bin_prot
>= "v0.17.0"
- colibri2
-
conduit
>= "0.12.0" & < "1.0.0"
-
core
>= "v0.17.0"
-
core_kernel
>= "v0.17.0"
-
core_unix
>= "v0.17.0"
-
earlybird
>= "1.2.0"
-
eliom
>= "10.1.0"
-
grace
>= "0.2.0"
-
incremental
>= "v0.17.0"
-
kqueue
>= "0.2.0"
-
pgocaml_ppx
>= "4.2"
- poll
-
posixat
>= "v0.17.0"
-
ppx_bap
< "v0.14.0"
- rea
-
time_now
>= "v0.17.0"
-
toplevel_backend
>= "v0.17.0"
-
toplevel_expect_test
>= "v0.17.0"
-
vscoq-language-server
>= "2.1.0+coq8.19"
- yices2_bindings
Conflicts
None