package ocaml-migrate-parsetree
Install
Dune Dependency
Authors
Maintainers
Sources
sha256=83e4955a6fd6b494646ab92c476840ea96b5fb434435c287e7ad3e6efadc8338
sha512=7da86f9596dd1439990a6f087fdeba64a0f3ce2634473be4cca92ecc02b6fcd97917956890fbe35b3cba5a126d007afec6ede1e4afd0a5218c89fd6079ad4182
Description
Deprecated. Please, use Ppxlib instead. More info on https://ocaml.org/changelog/2023-10-23-omp-deprecation
Convert OCaml parsetrees between different versions
This library converts parsetrees, outcometree and ast mappers between different OCaml versions. High-level functions help making PPX rewriters independent of a compiler version.
README
OCaml-migrate-parsetree
Convert OCaml parsetrees between different major versions
This library converts between parsetrees of different OCaml versions.
Supported versions are 4.02, 4.03, 4.04, 4.05, 4.06, 4.07, and 4.08. For each version, there is a snapshot of the parsetree and conversion functions to the next and/or previous version.
Asts
module Ast_402, Ast_403, Ast_404, Ast_405, Ast_406, Ast_407, Ast_408 : sig
(* These two modules didn't change between compiler versions.
Just share the ones from compiler-libs. *)
module Location = Location
module Longident = Longident
(* Version specific copy of AST *)
module Asttypes
module Parsetree
module Outcometree
(* Other modules that are useful for implementing PPX.
Docstrings and Ast_mapper only contain general definitions
In particular, the internal state used by compiler-libs has been
removed.
Also equalities are lost for abstract types (Docstring.docstring). *)
module Docstrings
module Ast_helper
module Ast_mapper
(* Magic numbers used for marshalling *)
module Config : sig
val ast_impl_magic_number : string
val ast_intf_magic_number : string
end
end
These embed copies of AST definitions for each supported OCaml major version.
The AST matching the version of the OCaml toolchain will contain equalities relating the copy of types to the definitions from compiler-libs. For instance, when installed with OCaml 4.04.x, Ast_404.Parsetree
looks like.
Migration modules
For each pair of versions $(n)
and $(n+1)
, the two modules Migrate_parsetree_$(n)_$(n+1)
and Migrate_parsetree_$(n+1)_$(n)
convert the AST forward and backward.
The forward conversion is total while the backward conversion is partial: when a feature is not available in a previous version of the parsetree, a Migrate_parsetree_def.Migration_error
exception is raised detailing the failure case.
Migrate_parsetree_versions
abstract versions of the compiler. Each version is represented as a module with OCaml_version
signature. Instances are named OCaml_402
, OCaml_403
, ... OCaml_current
is an alias to the version of the current compiler. The Convert
functor takes two versions of OCaml and produce conversion functions.
Finally, the Migrate_parsetree_ast_io
provides an easy interface for marshalling/unmarshalling.
Migrate_parsetree.Driver
The Migrate_parsetree.Driver
provides an API for ppx rewriters to register OCaml AST rewriters. Ppx rewriters using this API can be used as standalone rewriter executable or as part of a driver including several rewriters.
Using a single driver for several rewritings has the advantage that it is faster. Especially when using many ppx rewriters, it can speed up compilation a lot.
If using Jbuilder, you can consult the Jbuilder manual to see how to define and use ppx rewriters. Jbuilder automatically creates drivers based on ocaml-migrate-parsetree on demand.
The rest of this section describes how to do things manually or with ocamlbuild.
Building a custom driver using ocamlfind
To build a custom driver using ocamlfind, simply link all the ppx rewriter libraries together with the ocaml-migrate-parsetree.driver-main
package at the end:
ocamlfind ocamlopt -predicates ppx_driver -o ppx -linkpkg \
-package ppx_sexp_conv -package ppx_bin_prot \
-package ocaml-migrate-parsetree.driver-main
Normally, ocaml-migrate-parsetree based rewriters should be build with the approriate -linkall
option on individual libraries. If one is missing this option, the rewriter might not get linked in. If this is the case, a workaround is to pass -linkall
when linking the custom driver.
The resulting ppx
program can be used as follow:
./ppx file.ml
to print the transformed codeocamlc -pp './ppx --as-pp' ...
to use it as a pre-processorocamlc -ppx './ppx --as-ppx' ...
to use it as a-ppx
rewriter
Development
It started from the work of Alain Frisch in ppx_tools.
The library is distributed under LGPL 2.1 and is copyright INRIA.
Adding a new OCaml version
We use Cinaps to generate boilerplate. You can install it via opam: opam install cinaps
.
Add the new version in src/cinaps.ml supported_versions
.
Snapshot the ast in file "asts/ast_NEW.ml".
Define the modules
Location
andLongident
as aliases to corresponding modules from compiler-libs.Copy
Asttypes
,Parsetree
,Outcometree
,Docstrings
,Ast_helper
andAst_mapper
from the upstream files inparsing/
directory.Global state and definitions referencing external values should be removed from
Docstrings
andAst_mapper
. Take a look at existing snapshots.Create a
Config
module containingast_impl_magic_number
ast_impl_magic_number
from upstreamConfig
Call
tools/add_special_comments.native
on the file
Add migration functions:
Manually compile the ast (
ocamlc -c ast_NEW.ml
)Using
gencopy
from ppx_tools, generate copy code to and from previous version (assuming it is 404):
gencopy -I . -map Ast_404:Ast_NEW Ast_404.Parsetree.expression Ast_404.Parsetree.toplevel_phrase Ast_404.Outcometree.out_phrase > migrate_parsetree_404_NEW_migrate.ml
gencopy -I . -map Ast_NEW:Ast_404 Ast_NEW.Parsetree.expression Ast_NEW.Parsetree.toplevel_phrase Ast_NEW.Outcometree.out_phrase > migrate_parsetree_NEW_404_migrate.ml
Fix the generated code by implementing new cases
By default generated code use very long identifiers, simplify unambiguous ones (e.g.
copy_Ast_NEW_Parsetree_structure
->copy_structure
). The migration functor expects specific names, look atMigrate_parsetree_versions
interface.
TODO: specialize and improve gencopy for these cases
Add mapper lifting functions in the files migrate_parsetree_NEW_404.ml
and migrate_parsetree_404_NEW.ml
:
include the corresponding
Migrate_parsetree_40x_40y_migrate
moduledefine
copy_mapper
function, look at existingMigrate_parsetree_40x_40y
for guidance.
At any time, you can expand boilerplate code by running make cinaps
.
Update build system:
in Makefile, add "src/ast_NEW.ml" to
OCAML_ASTS
and migration modules toOBJECTS
make sure
make cinaps
reaches a fixed point :)make
should succeed
Dependencies (4)
-
ocaml
>= "4.02.3" & < "4.09.0"
-
dune
>= "1.6.0"
- ppx_derivers
- result
Dev Dependencies
None
-
async
>= "v0.9.0" & < "v0.12.0"
-
async_durable
< "v0.12.0"
-
async_extended
>= "v0.9.0"
-
async_extra
>= "v0.9.0" & < "v0.12.0"
-
async_find
>= "v0.9.0" & < "v0.12.0"
-
async_inotify
>= "v0.9.0" & < "v0.12.0"
-
async_interactive
< "v0.12.0"
-
async_js
< "v0.12.0"
-
async_kernel
>= "v0.9.0" & < "v0.12.0"
-
async_parallel
>= "v0.9.0"
-
async_rpc_kernel
>= "v0.9.0" & < "v0.12.0"
-
async_sendfile
< "v0.12.0"
-
async_shell
>= "v0.9.0" & < "v0.12.0"
-
async_smtp
>= "v0.9.0" & < "v0.12.0"
-
async_ssl
>= "v0.9.0" & < "v0.12.0"
-
async_unix
>= "v0.9.0" & < "v0.12.0"
-
bignum
>= "v0.9.0" & < "v0.12.0"
-
bin_prot
>= "v0.9.0" & < "v0.12.0"
-
bisect_ppx
>= "1.3.0" & < "1.4.2"
-
bitstring
>= "3.0.0" & < "4.0.0"
-
command_rpc
< "v0.12.0"
-
conduit-lwt-unix
< "1.3.0"
-
configurator
< "v0.10.0"
-
core
>= "v0.9.0" & < "v0.12.0"
-
core_bench
>= "v0.9.0" & < "v0.12.0"
-
core_extended
>= "v0.9.0" & < "v0.12.0"
-
core_kernel
>= "v0.9.0" & < "v0.12.0"
-
core_profiler
>= "v0.9.0" & < "v0.12.0"
-
cstruct
= "2.4.1"
-
csvfields
< "v0.12.0"
-
delimited_parsing
< "v0.12.0"
-
dockerfile
>= "3.0.0" & < "6.0.0"
-
dockerfile-cmd
< "6.0.0"
-
dockerfile-opam
>= "4.0.0" & < "6.0.0"
-
ecaml
< "v0.12.0"
-
elpi
< "1.11.1"
-
email_message
>= "v0.9.0" & < "v0.12.0"
-
expect_test_helpers
< "v0.12.0"
-
expect_test_helpers_kernel
< "v0.12.0"
-
fieldslib
>= "v0.9.0" & < "v0.12.0"
-
fstar
>= "0.9.6.0" & < "2021.06.06"
-
GT
< "0.4.0"
-
gdbprofiler
>= "0.2" & < "0.4"
-
graphql
< "0.4.0"
-
graphql_parser
< "0.9.0"
-
graphql_ppx
< "0.7.1"
-
incr_dom
< "v0.12.0"
-
incr_dom_widgets
< "v0.12.0"
-
incr_map
< "v0.12.0"
-
incr_select
< "v0.12.0"
-
incremental
>= "v0.9.0" & < "v0.12.0"
-
incremental_kernel
>= "v0.9.0"
-
ipaddr
= "2.8.0"
- jane-street-tests
-
jenga
>= "v0.9.0"
-
js_of_ocaml
>= "3.0" & < "3.5.0"
-
js_of_ocaml-compiler
>= "3.5.0" & < "3.8.0"
-
js_of_ocaml-ppx
< "3.5.0"
-
js_of_ocaml-ppx_deriving_json
>= "3.5.0" & < "3.8.0"
- json-wheel_jane_street_overlay
-
jupyter
>= "2.0.0" & < "2.2.2"
- kubecaml
-
lablqml
= "0.5.2"
-
landmarks
= "1.3"
-
levenshtein
>= "1.1.3"
-
line-up-words
< "v0.12.0"
-
lwt
>= "3.1.0" & < "4.0.0"
-
lwt_ppx
< "1.2.4"
-
mdx
>= "1.2.0" & < "1.8.0"
- mecab
-
memtrace_viewer
< "v0.15.0"
-
mirage-profile
= "0.8.2"
-
mlpost
>= "0.9"
-
mlt_parser
< "v0.12.0"
-
multipart-form-data
= "0.2.0"
-
notty_async
< "v0.12.0"
-
nsq
>= "0.2.4"
-
obus
>= "1.2.0" & < "1.2.3"
-
ocaml-basics
>= "0.5.0"
- ocaml-logicalform
- ocaml-migrate-parsetree-ocamlbuild
-
ocaml-monadic
>= "0.4.0" & < "0.5"
-
ocaml_plugin
>= "v0.9.0" & < "v0.12.0"
-
ocamlformat
< "0.14.0"
-
odoc
>= "2.0.0" & < "2.1.0"
-
omonad
>= "0.3.3"
- openai-gym
- otetris
-
parsexp
< "v0.11.0"
-
parsexp_io
< "v0.12.0"
- partition_map
- passmaker
-
patdiff
>= "v0.9.0" & < "v0.12.0"
-
patience_diff
>= "v0.9.0" & < "v0.12.0"
-
pgocaml
>= "3.1" & < "4.0"
-
pgocaml_ppx
< "4.3.0"
-
pla
>= "1.2" & < "2.0"
-
posixat
>= "v0.10.0" & < "v0.12.0"
-
ppx_assert
>= "v0.9.0" & < "v0.12.0"
-
ppx_ast
< "v0.11.0"
-
ppx_base
< "v0.12.0"
-
ppx_bench
>= "v0.9.0" & < "v0.12.0"
-
ppx_bigarray
>= "3.0.0"
-
ppx_bin_prot
>= "v0.9.0" & < "v0.12.0"
-
ppx_bitstring
>= "2.0.0" & < "4.0.0"
-
ppx_blob
>= "0.3.0" & < "0.7.1"
-
ppx_compare
>= "v0.9.0" & < "v0.12.0"
-
ppx_compose
< "0.1.0"
-
ppx_conv_func
>= "v0.9.0" & < "v0.12.0"
-
ppx_cstruct
>= "3.0.1" & < "6.0.0"
-
ppx_cstubs
< "0.4.0"
-
ppx_csv_conv
>= "v0.9.0" & < "v0.12.0"
-
ppx_custom_printf
>= "v0.9.0" & < "v0.12.0"
-
ppx_defer
= "0.3.0"
-
ppx_deriving
>= "4.2" & < "5.2"
- ppx_deriving_argparse
-
ppx_driver
>= "v0.9.0" & < "v0.11.0"
- ppx_dryunit
-
ppx_enumerate
>= "v0.9.0" & < "v0.12.0"
-
ppx_expect
>= "v0.9.0" & < "v0.12.0"
-
ppx_fail
>= "v0.9.0" & < "v0.12.0"
- ppx_fast_pipe
-
ppx_fields_conv
>= "v0.9.0" & < "v0.12.0"
-
ppx_gen_rec
< "2.0.0"
-
ppx_hash
< "v0.12.0"
-
ppx_here
>= "v0.9.0" & < "v0.12.0"
-
ppx_implicits
>= "0.2.0"
-
ppx_import
>= "1.5-3-gbd627d5" & < "1.8.0"
-
ppx_inline_test
>= "v0.9.0" & < "v0.12.0"
-
ppx_jane
>= "v0.9.0" & < "v0.12.0"
-
ppx_js_style
< "v0.12.0"
-
ppx_jsobject_conv
>= "0.5.0" & < "0.9.0"
-
ppx_let
>= "v0.9.0" & < "v0.12.0"
-
ppx_metaquot
< "v0.11.0"
- ppx_nanocaml
-
ppx_optional
< "v0.12.0"
-
ppx_pipebang
>= "v0.9.0" & < "v0.12.0"
-
ppx_regexp
< "0.4.3"
-
ppx_relit
>= "0.2.0"
-
ppx_sexp_conv
>= "v0.9.0" & < "v0.12.0"
-
ppx_sexp_message
>= "v0.9.0" & < "v0.12.0"
-
ppx_sexp_value
>= "v0.9.0" & < "v0.12.0"
- ppx_sqlexpr
-
ppx_tools_versioned
= "5.2.2"
-
ppx_traverse
< "v0.11.0"
-
ppx_type_conv
>= "v0.9.0" & < "v0.11.0"
-
ppx_typerep_conv
>= "v0.9.0" & < "v0.12.0"
-
ppx_tyre
< "0.4.3"
-
ppx_variants_conv
>= "v0.9.0" & < "v0.12.0"
- ppx_view
-
ppx_xml_conv
>= "v0.9.0" & < "v0.12.0"
-
ppxfind
< "1.4"
-
ppxlib
< "0.14.0"
-
ppxx
>= "2.0.0" & < "2.5.0"
- prettiest
-
protocol-9p
>= "0.11.2" & < "1.0.0"
-
protocol-9p-unix
= "0.11.3" | = "0.12.1"
-
protocol_version_header
< "v0.12.0"
- pumping
-
re2
>= "v0.9.0" & < "v0.12.0"
-
reason
>= "1.11.0" & < "3.6.2"
- reason-parser
-
record_builder
< "v0.12.0"
- relit-reason
-
relit_helper
>= "0.2.0"
-
resource_cache
< "v0.12.0"
-
rpc_parallel
>= "v0.9.0" & < "v0.12.0"
-
scaml
< "1.5.0"
-
sedlex
>= "1.99.4" & < "2.3"
-
sequencer_table
< "v0.12.0"
-
sexp_pretty
< "v0.12.0"
-
shared-memory-ring
= "3.0.1"
-
splay_tree
< "v0.12.0"
-
splittable_random
< "v0.12.0"
-
spotlib
= "4.0.3"
-
ssh-agent
< "0.2.0"
- sslconf
-
string_dict
< "v0.12.0"
-
tcpip
>= "3.4.1" & < "3.7.0"
-
textutils
>= "v0.9.0" & < "v0.12.0"
-
textutils_kernel
< "v0.12.0"
- tezos-benchmark
-
toplevel_expect_test
>= "v0.9.1" & < "v0.12.0"
-
topological_sort
< "v0.12.0"
-
treeprint
= "2.2.0"
-
typerep_extended
>= "v0.9.0"
-
unmagic
>= "1.0.3"
-
uri
>= "1.9.4" & < "2.0.0"
-
variantslib
>= "v0.9.0" & < "v0.12.0"
-
virtual_dom
< "v0.12.0"
-
vmnet
>= "1.3.0" & < "1.3.2"
-
wcs-lib
>= "2017-05-26.02"
-
yaml
< "1.0.0"
- yara
- zarith-ppx