mte/unikernel/duniverse/ppxlib/ast/versions.ml

729 lines
28 KiB
OCaml
Raw Normal View History

2025-11-11 02:07:51 +01:00
(**************************************************************************)
(* *)
(* OCaml Migrate Parsetree *)
(* *)
(* Frédéric Bour *)
(* Jérémie Dimino, Jane Street Europe *)
(* *)
(* Copyright 2017 Institut National de Recherche en Informatique et *)
(* en Automatique (INRIA). *)
(* *)
(* All rights reserved. This file is distributed under the terms of *)
(* the GNU Lesser General Public License version 2.1, with the *)
(* special exception on linking described in the file LICENSE. *)
(* *)
(**************************************************************************)
(* BEGIN of BLACK MAGIC *)
(*$ open Ast_cinaps_helpers $*)
type _ witnesses = ..
type _ migration = ..
type _ migration += Undefined : _ migration
type 'a migration_info = {
mutable next_version : 'a migration;
mutable previous_version : 'a migration;
}
(** Abstract view of a version of an OCaml Ast *)
module type Ast = sig
(*$ foreach_module (fun m types ->
printf " module %s : sig\n" m;
List.iter types ~f:(printf " type %s\n");
printf " end\n"
)
*)
module Parsetree : sig
type structure
type signature
type toplevel_phrase
type core_type
type expression
type pattern
type case
type type_declaration
type type_extension
type extension_constructor
type class_expr
type class_field
type class_type
type class_signature
type class_type_field
type module_expr
type module_type
type signature_item
type structure_item
end
(*$*)
module Config : sig
val ast_impl_magic_number : string
val ast_intf_magic_number : string
end
end
(* Shortcuts for talking about ast types outside of the module language *)
type 'a _types = 'a constraint 'a
= <
(*$ foreach_type (fun _ s -> printf " %-21s : _;\n" s) *)
structure : _;
signature : _;
toplevel_phrase : _;
core_type : _;
expression : _;
pattern : _;
case : _;
type_declaration : _;
type_extension : _;
extension_constructor : _;
class_expr : _;
class_field : _;
class_type : _;
class_signature : _;
class_type_field : _;
module_expr : _;
module_type : _;
signature_item : _;
structure_item : _;
(*$*)
>
;;
(*$ foreach_type (fun _ s ->
printf "type 'a get_%s =\n" s;
printf " 'x constraint 'a _types = < %s : 'x; .. >\n" s
) *)
type 'a get_structure =
'x constraint 'a _types = < structure : 'x; .. >
type 'a get_signature =
'x constraint 'a _types = < signature : 'x; .. >
type 'a get_toplevel_phrase =
'x constraint 'a _types = < toplevel_phrase : 'x; .. >
type 'a get_core_type =
'x constraint 'a _types = < core_type : 'x; .. >
type 'a get_expression =
'x constraint 'a _types = < expression : 'x; .. >
type 'a get_pattern =
'x constraint 'a _types = < pattern : 'x; .. >
type 'a get_case =
'x constraint 'a _types = < case : 'x; .. >
type 'a get_type_declaration =
'x constraint 'a _types = < type_declaration : 'x; .. >
type 'a get_type_extension =
'x constraint 'a _types = < type_extension : 'x; .. >
type 'a get_extension_constructor =
'x constraint 'a _types = < extension_constructor : 'x; .. >
type 'a get_class_expr =
'x constraint 'a _types = < class_expr : 'x; .. >
type 'a get_class_field =
'x constraint 'a _types = < class_field : 'x; .. >
type 'a get_class_type =
'x constraint 'a _types = < class_type : 'x; .. >
type 'a get_class_signature =
'x constraint 'a _types = < class_signature : 'x; .. >
type 'a get_class_type_field =
'x constraint 'a _types = < class_type_field : 'x; .. >
type 'a get_module_expr =
'x constraint 'a _types = < module_expr : 'x; .. >
type 'a get_module_type =
'x constraint 'a _types = < module_type : 'x; .. >
type 'a get_signature_item =
'x constraint 'a _types = < signature_item : 'x; .. >
type 'a get_structure_item =
'x constraint 'a _types = < structure_item : 'x; .. >
(*$*)
module type OCaml_version = sig
module Ast : Ast
val version : int
val string_version : string
type types = <
(*$ foreach_type (fun m s -> printf " %-21s : Ast.%s.%s;\n" s m s)*)
structure : Ast.Parsetree.structure;
signature : Ast.Parsetree.signature;
toplevel_phrase : Ast.Parsetree.toplevel_phrase;
core_type : Ast.Parsetree.core_type;
expression : Ast.Parsetree.expression;
pattern : Ast.Parsetree.pattern;
case : Ast.Parsetree.case;
type_declaration : Ast.Parsetree.type_declaration;
type_extension : Ast.Parsetree.type_extension;
extension_constructor : Ast.Parsetree.extension_constructor;
class_expr : Ast.Parsetree.class_expr;
class_field : Ast.Parsetree.class_field;
class_type : Ast.Parsetree.class_type;
class_signature : Ast.Parsetree.class_signature;
class_type_field : Ast.Parsetree.class_type_field;
module_expr : Ast.Parsetree.module_expr;
module_type : Ast.Parsetree.module_type;
signature_item : Ast.Parsetree.signature_item;
structure_item : Ast.Parsetree.structure_item;
(*$*)
> _types
type _ witnesses += Version : types witnesses
val migration_info : types migration_info
end
module Make_witness(Ast : Ast) =
struct
type types = <
(*$ foreach_type (fun m s -> printf " %-21s : Ast.%s.%s;\n" s m s)*)
structure : Ast.Parsetree.structure;
signature : Ast.Parsetree.signature;
toplevel_phrase : Ast.Parsetree.toplevel_phrase;
core_type : Ast.Parsetree.core_type;
expression : Ast.Parsetree.expression;
pattern : Ast.Parsetree.pattern;
case : Ast.Parsetree.case;
type_declaration : Ast.Parsetree.type_declaration;
type_extension : Ast.Parsetree.type_extension;
extension_constructor : Ast.Parsetree.extension_constructor;
class_expr : Ast.Parsetree.class_expr;
class_field : Ast.Parsetree.class_field;
class_type : Ast.Parsetree.class_type;
class_signature : Ast.Parsetree.class_signature;
class_type_field : Ast.Parsetree.class_type_field;
module_expr : Ast.Parsetree.module_expr;
module_type : Ast.Parsetree.module_type;
signature_item : Ast.Parsetree.signature_item;
structure_item : Ast.Parsetree.structure_item;
(*$*)
> _types
type _ witnesses += Version : types witnesses
let migration_info : types migration_info =
{ next_version = Undefined; previous_version = Undefined }
end
type 'types ocaml_version =
(module OCaml_version
(*$ let sep = with_then_and () in
foreach_type (fun m s ->
printf " %t type Ast.%s.%s = 'types get_%s\n" sep m s s) *)
with type Ast.Parsetree.structure = 'types get_structure
and type Ast.Parsetree.signature = 'types get_signature
and type Ast.Parsetree.toplevel_phrase = 'types get_toplevel_phrase
and type Ast.Parsetree.core_type = 'types get_core_type
and type Ast.Parsetree.expression = 'types get_expression
and type Ast.Parsetree.pattern = 'types get_pattern
and type Ast.Parsetree.case = 'types get_case
and type Ast.Parsetree.type_declaration = 'types get_type_declaration
and type Ast.Parsetree.type_extension = 'types get_type_extension
and type Ast.Parsetree.extension_constructor = 'types get_extension_constructor
and type Ast.Parsetree.class_expr = 'types get_class_expr
and type Ast.Parsetree.class_field = 'types get_class_field
and type Ast.Parsetree.class_type = 'types get_class_type
and type Ast.Parsetree.class_signature = 'types get_class_signature
and type Ast.Parsetree.class_type_field = 'types get_class_type_field
and type Ast.Parsetree.module_expr = 'types get_module_expr
and type Ast.Parsetree.module_type = 'types get_module_type
and type Ast.Parsetree.signature_item = 'types get_signature_item
and type Ast.Parsetree.structure_item = 'types get_structure_item
(*$*)
)
type ('from, 'to_) migration_functions = {
(*$ foreach_type (fun _ s ->
printf " copy_%s: 'from get_%s -> 'to_ get_%s;\n" s s s) *)
copy_structure: 'from get_structure -> 'to_ get_structure;
copy_signature: 'from get_signature -> 'to_ get_signature;
copy_toplevel_phrase: 'from get_toplevel_phrase -> 'to_ get_toplevel_phrase;
copy_core_type: 'from get_core_type -> 'to_ get_core_type;
copy_expression: 'from get_expression -> 'to_ get_expression;
copy_pattern: 'from get_pattern -> 'to_ get_pattern;
copy_case: 'from get_case -> 'to_ get_case;
copy_type_declaration: 'from get_type_declaration -> 'to_ get_type_declaration;
copy_type_extension: 'from get_type_extension -> 'to_ get_type_extension;
copy_extension_constructor: 'from get_extension_constructor -> 'to_ get_extension_constructor;
copy_class_expr: 'from get_class_expr -> 'to_ get_class_expr;
copy_class_field: 'from get_class_field -> 'to_ get_class_field;
copy_class_type: 'from get_class_type -> 'to_ get_class_type;
copy_class_signature: 'from get_class_signature -> 'to_ get_class_signature;
copy_class_type_field: 'from get_class_type_field -> 'to_ get_class_type_field;
copy_module_expr: 'from get_module_expr -> 'to_ get_module_expr;
copy_module_type: 'from get_module_type -> 'to_ get_module_type;
copy_signature_item: 'from get_signature_item -> 'to_ get_signature_item;
copy_structure_item: 'from get_structure_item -> 'to_ get_structure_item;
(*$*)
}
let id x = x
let migration_identity : ('a, 'a) migration_functions = {
(*$ foreach_type (fun _ s -> printf " copy_%s = id;\n" s) *)
copy_structure = id;
copy_signature = id;
copy_toplevel_phrase = id;
copy_core_type = id;
copy_expression = id;
copy_pattern = id;
copy_case = id;
copy_type_declaration = id;
copy_type_extension = id;
copy_extension_constructor = id;
copy_class_expr = id;
copy_class_field = id;
copy_class_type = id;
copy_class_signature = id;
copy_class_type_field = id;
copy_module_expr = id;
copy_module_type = id;
copy_signature_item = id;
copy_structure_item = id;
(*$*)
}
let compose f g x = f (g x)
let migration_compose (ab : ('a, 'b) migration_functions) (bc : ('b, 'c) migration_functions) : ('a, 'c) migration_functions = {
(*$ foreach_type (fun _ s ->
printf " copy_%-21s = compose bc.copy_%-21s ab.copy_%s;\n" s s s) *)
copy_structure = compose bc.copy_structure ab.copy_structure;
copy_signature = compose bc.copy_signature ab.copy_signature;
copy_toplevel_phrase = compose bc.copy_toplevel_phrase ab.copy_toplevel_phrase;
copy_core_type = compose bc.copy_core_type ab.copy_core_type;
copy_expression = compose bc.copy_expression ab.copy_expression;
copy_pattern = compose bc.copy_pattern ab.copy_pattern;
copy_case = compose bc.copy_case ab.copy_case;
copy_type_declaration = compose bc.copy_type_declaration ab.copy_type_declaration;
copy_type_extension = compose bc.copy_type_extension ab.copy_type_extension;
copy_extension_constructor = compose bc.copy_extension_constructor ab.copy_extension_constructor;
copy_class_expr = compose bc.copy_class_expr ab.copy_class_expr;
copy_class_field = compose bc.copy_class_field ab.copy_class_field;
copy_class_type = compose bc.copy_class_type ab.copy_class_type;
copy_class_signature = compose bc.copy_class_signature ab.copy_class_signature;
copy_class_type_field = compose bc.copy_class_type_field ab.copy_class_type_field;
copy_module_expr = compose bc.copy_module_expr ab.copy_module_expr;
copy_module_type = compose bc.copy_module_type ab.copy_module_type;
copy_signature_item = compose bc.copy_signature_item ab.copy_signature_item;
copy_structure_item = compose bc.copy_structure_item ab.copy_structure_item;
(*$*)
}
type _ migration += Migration : 'from ocaml_version * ('from, 'to_) migration_functions * 'to_ ocaml_version -> 'from migration
module type Migrate_module = sig
module From : Ast
module To : Ast
(*$ foreach_type (fun m s ->
printf " val copy_%-21s: From.%s.%s -> To.%s.%s\n" s m s m s) *)
val copy_structure : From.Parsetree.structure -> To.Parsetree.structure
val copy_signature : From.Parsetree.signature -> To.Parsetree.signature
val copy_toplevel_phrase : From.Parsetree.toplevel_phrase -> To.Parsetree.toplevel_phrase
val copy_core_type : From.Parsetree.core_type -> To.Parsetree.core_type
val copy_expression : From.Parsetree.expression -> To.Parsetree.expression
val copy_pattern : From.Parsetree.pattern -> To.Parsetree.pattern
val copy_case : From.Parsetree.case -> To.Parsetree.case
val copy_type_declaration : From.Parsetree.type_declaration -> To.Parsetree.type_declaration
val copy_type_extension : From.Parsetree.type_extension -> To.Parsetree.type_extension
val copy_extension_constructor: From.Parsetree.extension_constructor -> To.Parsetree.extension_constructor
val copy_class_expr : From.Parsetree.class_expr -> To.Parsetree.class_expr
val copy_class_field : From.Parsetree.class_field -> To.Parsetree.class_field
val copy_class_type : From.Parsetree.class_type -> To.Parsetree.class_type
val copy_class_signature : From.Parsetree.class_signature -> To.Parsetree.class_signature
val copy_class_type_field : From.Parsetree.class_type_field -> To.Parsetree.class_type_field
val copy_module_expr : From.Parsetree.module_expr -> To.Parsetree.module_expr
val copy_module_type : From.Parsetree.module_type -> To.Parsetree.module_type
val copy_signature_item : From.Parsetree.signature_item -> To.Parsetree.signature_item
val copy_structure_item : From.Parsetree.structure_item -> To.Parsetree.structure_item
(*$*)
end
module Migration_functions
(A : OCaml_version) (B : OCaml_version)
(A_to_B : Migrate_module with module From = A.Ast and module To = B.Ast)
=
struct
let migration_functions : (A.types, B.types) migration_functions =
let open A_to_B in
{
(*$ foreach_type (fun _ s -> printf " copy_%s;\n" s) *)
copy_structure;
copy_signature;
copy_toplevel_phrase;
copy_core_type;
copy_expression;
copy_pattern;
copy_case;
copy_type_declaration;
copy_type_extension;
copy_extension_constructor;
copy_class_expr;
copy_class_field;
copy_class_type;
copy_class_signature;
copy_class_type_field;
copy_module_expr;
copy_module_type;
copy_signature_item;
copy_structure_item;
(*$*)
}
end
module Register_migration (A : OCaml_version) (B : OCaml_version)
(A_to_B : Migrate_module with module From = A.Ast and module To = B.Ast)
(B_to_A : Migrate_module with module From = B.Ast and module To = A.Ast)
=
struct
let () = (
let is_undefined : type a. a migration -> bool = function
| Undefined -> true
| _ -> false
in
assert (A.version < B.version);
assert (is_undefined A.migration_info.next_version);
assert (is_undefined B.migration_info.previous_version);
let module A_to_B_fun = Migration_functions(A)(B)(A_to_B) in
let module B_to_A_fun = Migration_functions(B)(A)(B_to_A) in
A.migration_info.next_version <-
Migration ((module A), A_to_B_fun.migration_functions, (module B));
B.migration_info.previous_version <-
Migration ((module B), B_to_A_fun.migration_functions, (module A));
)
end
type 'from immediate_migration =
| No_migration : 'from immediate_migration
| Immediate_migration
: ('from, 'to_) migration_functions * 'to_ ocaml_version
-> 'from immediate_migration
let immediate_migration
(*$ foreach_type (fun _ s -> printf " (type %s)\n" s) *)
(type structure)
(type signature)
(type toplevel_phrase)
(type core_type)
(type expression)
(type pattern)
(type case)
(type type_declaration)
(type type_extension)
(type extension_constructor)
(type class_expr)
(type class_field)
(type class_type)
(type class_signature)
(type class_type_field)
(type module_expr)
(type module_type)
(type signature_item)
(type structure_item)
(*$*)
((module A) : <
(*$ foreach_type (fun _ s -> printf " %-21s : %s;\n" s s) *)
structure : structure;
signature : signature;
toplevel_phrase : toplevel_phrase;
core_type : core_type;
expression : expression;
pattern : pattern;
case : case;
type_declaration : type_declaration;
type_extension : type_extension;
extension_constructor : extension_constructor;
class_expr : class_expr;
class_field : class_field;
class_type : class_type;
class_signature : class_signature;
class_type_field : class_type_field;
module_expr : module_expr;
module_type : module_type;
signature_item : signature_item;
structure_item : structure_item;
(*$*)
> ocaml_version)
direction
=
let version = match direction with
| `Next -> A.migration_info.next_version
| `Previous -> A.migration_info.previous_version
in
match version with
| Undefined -> No_migration
| Migration (_, funs, to_) -> Immediate_migration (funs, to_)
| _ -> assert false
let migrate
(*$ foreach_type (fun _ s -> printf " (type %s1) (type %s2)\n" s s) *)
(type structure1) (type structure2)
(type signature1) (type signature2)
(type toplevel_phrase1) (type toplevel_phrase2)
(type core_type1) (type core_type2)
(type expression1) (type expression2)
(type pattern1) (type pattern2)
(type case1) (type case2)
(type type_declaration1) (type type_declaration2)
(type type_extension1) (type type_extension2)
(type extension_constructor1) (type extension_constructor2)
(type class_expr1) (type class_expr2)
(type class_field1) (type class_field2)
(type class_type1) (type class_type2)
(type class_signature1) (type class_signature2)
(type class_type_field1) (type class_type_field2)
(type module_expr1) (type module_expr2)
(type module_type1) (type module_type2)
(type signature_item1) (type signature_item2)
(type structure_item1) (type structure_item2)
(*$*)
((module A) : <
(*$ foreach_type (fun _ s -> printf " %-21s : %s1;\n" s s) *)
structure : structure1;
signature : signature1;
toplevel_phrase : toplevel_phrase1;
core_type : core_type1;
expression : expression1;
pattern : pattern1;
case : case1;
type_declaration : type_declaration1;
type_extension : type_extension1;
extension_constructor : extension_constructor1;
class_expr : class_expr1;
class_field : class_field1;
class_type : class_type1;
class_signature : class_signature1;
class_type_field : class_type_field1;
module_expr : module_expr1;
module_type : module_type1;
signature_item : signature_item1;
structure_item : structure_item1;
(*$*)
> ocaml_version)
((module B) : <
(*$ foreach_type (fun _ s -> printf " %-21s : %s2;\n" s s) *)
structure : structure2;
signature : signature2;
toplevel_phrase : toplevel_phrase2;
core_type : core_type2;
expression : expression2;
pattern : pattern2;
case : case2;
type_declaration : type_declaration2;
type_extension : type_extension2;
extension_constructor : extension_constructor2;
class_expr : class_expr2;
class_field : class_field2;
class_type : class_type2;
class_signature : class_signature2;
class_type_field : class_type_field2;
module_expr : module_expr2;
module_type : module_type2;
signature_item : signature_item2;
structure_item : structure_item2;
(*$*)
> ocaml_version)
: (A.types, B.types) migration_functions
=
match A.Version with
| B.Version -> migration_identity
| _ ->
let direction = if A.version < B.version then `Next else `Previous in
let rec migrate (m : A.types immediate_migration) : (A.types, B.types) migration_functions =
match m with
| No_migration -> assert false
| Immediate_migration (f, (module To)) ->
match To.Version with
| B.Version -> f
| _ ->
match immediate_migration (module To) direction with
| No_migration -> assert false
| Immediate_migration (g, to2) ->
migrate (Immediate_migration (migration_compose f g, to2))
in
migrate (immediate_migration (module A) direction)
module Convert (A : OCaml_version) (B : OCaml_version) = struct
let {
(*$ foreach_type (fun _ s -> printf " copy_%s;\n" s) *)
copy_structure;
copy_signature;
copy_toplevel_phrase;
copy_core_type;
copy_expression;
copy_pattern;
copy_case;
copy_type_declaration;
copy_type_extension;
copy_extension_constructor;
copy_class_expr;
copy_class_field;
copy_class_type;
copy_class_signature;
copy_class_type_field;
copy_module_expr;
copy_module_type;
copy_signature_item;
copy_structure_item;
(*$*)
} : (A.types, B.types) migration_functions =
migrate (module A) (module B)
end
(*$ foreach_version (fun n version ->
printf "module OCaml_%d = struct\n" n;
printf " module Ast = Astlib.Ast_%d\n" n;
printf " include Make_witness(Astlib.Ast_%d)\n" n;
printf " let version = %d\n" n;
printf " let string_version = %S\n" version;
printf "end\n";
printf "let ocaml_%d : OCaml_%d.types ocaml_version = (module OCaml_%d)\n"
n n n;
)
*)
module OCaml_408 = struct
module Ast = Astlib.Ast_408
include Make_witness(Astlib.Ast_408)
let version = 408
let string_version = "4.08"
end
let ocaml_408 : OCaml_408.types ocaml_version = (module OCaml_408)
module OCaml_409 = struct
module Ast = Astlib.Ast_409
include Make_witness(Astlib.Ast_409)
let version = 409
let string_version = "4.09"
end
let ocaml_409 : OCaml_409.types ocaml_version = (module OCaml_409)
module OCaml_410 = struct
module Ast = Astlib.Ast_410
include Make_witness(Astlib.Ast_410)
let version = 410
let string_version = "4.10"
end
let ocaml_410 : OCaml_410.types ocaml_version = (module OCaml_410)
module OCaml_411 = struct
module Ast = Astlib.Ast_411
include Make_witness(Astlib.Ast_411)
let version = 411
let string_version = "4.11"
end
let ocaml_411 : OCaml_411.types ocaml_version = (module OCaml_411)
module OCaml_412 = struct
module Ast = Astlib.Ast_412
include Make_witness(Astlib.Ast_412)
let version = 412
let string_version = "4.12"
end
let ocaml_412 : OCaml_412.types ocaml_version = (module OCaml_412)
module OCaml_413 = struct
module Ast = Astlib.Ast_413
include Make_witness(Astlib.Ast_413)
let version = 413
let string_version = "4.13"
end
let ocaml_413 : OCaml_413.types ocaml_version = (module OCaml_413)
module OCaml_414 = struct
module Ast = Astlib.Ast_414
include Make_witness(Astlib.Ast_414)
let version = 414
let string_version = "4.14"
end
let ocaml_414 : OCaml_414.types ocaml_version = (module OCaml_414)
module OCaml_500 = struct
module Ast = Astlib.Ast_500
include Make_witness(Astlib.Ast_500)
let version = 500
let string_version = "5.0"
end
let ocaml_500 : OCaml_500.types ocaml_version = (module OCaml_500)
module OCaml_501 = struct
module Ast = Astlib.Ast_501
include Make_witness(Astlib.Ast_501)
let version = 501
let string_version = "5.1"
end
let ocaml_501 : OCaml_501.types ocaml_version = (module OCaml_501)
module OCaml_502 = struct
module Ast = Astlib.Ast_502
include Make_witness(Astlib.Ast_502)
let version = 502
let string_version = "5.2"
end
let ocaml_502 : OCaml_502.types ocaml_version = (module OCaml_502)
module OCaml_503 = struct
module Ast = Astlib.Ast_503
include Make_witness(Astlib.Ast_503)
let version = 503
let string_version = "5.3"
end
let ocaml_503 : OCaml_503.types ocaml_version = (module OCaml_503)
module OCaml_504 = struct
module Ast = Astlib.Ast_504
include Make_witness(Astlib.Ast_504)
let version = 504
let string_version = "5.4"
end
let ocaml_504 : OCaml_504.types ocaml_version = (module OCaml_504)
(*$*)
let all_versions : (module OCaml_version) list = [
(*$foreach_version (fun n _ ->
printf "(module OCaml_%d : OCaml_version);\n" n)*)
(module OCaml_408 : OCaml_version);
(module OCaml_409 : OCaml_version);
(module OCaml_410 : OCaml_version);
(module OCaml_411 : OCaml_version);
(module OCaml_412 : OCaml_version);
(module OCaml_413 : OCaml_version);
(module OCaml_414 : OCaml_version);
(module OCaml_500 : OCaml_version);
(module OCaml_501 : OCaml_version);
(module OCaml_502 : OCaml_version);
(module OCaml_503 : OCaml_version);
(module OCaml_504 : OCaml_version);
(*$*)
]
(*$foreach_version_pair (fun a b ->
printf "include Register_migration(OCaml_%d)(OCaml_%d)\n" a b;
printf " (Astlib.Migrate_%d_%d)(Astlib.Migrate_%d_%d)\n" a b b a
)
*)
include Register_migration(OCaml_408)(OCaml_409)
(Astlib.Migrate_408_409)(Astlib.Migrate_409_408)
include Register_migration(OCaml_409)(OCaml_410)
(Astlib.Migrate_409_410)(Astlib.Migrate_410_409)
include Register_migration(OCaml_410)(OCaml_411)
(Astlib.Migrate_410_411)(Astlib.Migrate_411_410)
include Register_migration(OCaml_411)(OCaml_412)
(Astlib.Migrate_411_412)(Astlib.Migrate_412_411)
include Register_migration(OCaml_412)(OCaml_413)
(Astlib.Migrate_412_413)(Astlib.Migrate_413_412)
include Register_migration(OCaml_413)(OCaml_414)
(Astlib.Migrate_413_414)(Astlib.Migrate_414_413)
include Register_migration(OCaml_414)(OCaml_500)
(Astlib.Migrate_414_500)(Astlib.Migrate_500_414)
include Register_migration(OCaml_500)(OCaml_501)
(Astlib.Migrate_500_501)(Astlib.Migrate_501_500)
include Register_migration(OCaml_501)(OCaml_502)
(Astlib.Migrate_501_502)(Astlib.Migrate_502_501)
include Register_migration(OCaml_502)(OCaml_503)
(Astlib.Migrate_502_503)(Astlib.Migrate_503_502)
include Register_migration(OCaml_503)(OCaml_504)
(Astlib.Migrate_503_504)(Astlib.Migrate_504_503)
(*$*)
module OCaml_current = OCaml_OCAML_VERSION
module Find_version = struct
type t = Impl of (module OCaml_version) | Intf of (module OCaml_version) | Unknown
let from_magic magic =
let rec loop = function
| [] -> Unknown
| (module Version : OCaml_version) :: tail ->
if Version.Ast.Config.ast_impl_magic_number = magic then
Impl (module Version)
else if Version.Ast.Config.ast_intf_magic_number = magic then
Intf (module Version)
else
loop tail
in
(* Traverse the versions from last to first:
if the magic numbers aren't unique among versions,
we want the latest version with a magic number match.
The situation in mind is trunk support. *)
let all_versions_top_down = List.rev all_versions in
loop all_versions_top_down
end