123 lines
3.6 KiB
Perl
123 lines
3.6 KiB
Perl
gencopy is a dev utility tool that we use to generate migration functions
|
|
skeletons when adding support for new compiler versions.
|
|
|
|
We can run it on two empty .ml files:
|
|
|
|
$ touch in.ml
|
|
$ touch out.ml
|
|
|
|
$ ../../dev/gencopy/gencopy.exe in.ml out.ml
|
|
open Stdlib0
|
|
let copy_location x = x
|
|
|
|
It then simply generates the headers which are a global open to stdlib0 and a
|
|
default copy function for location that one could overwrite if needed.
|
|
|
|
================= Simple types =================
|
|
|
|
We can test it on a pair of simple types, note that all types are expected to be
|
|
defined in submodules and not at the root as the ast_X.ml files are laid out that
|
|
way:
|
|
|
|
$ cat > in.ml << EOF
|
|
> module X = struct
|
|
> type r = {a: int; b: string}
|
|
> end
|
|
>
|
|
> module Y = struct
|
|
> type s = A of int | B of string
|
|
> end
|
|
> EOF
|
|
|
|
$ ../../dev/gencopy/gencopy.exe in.ml out.ml
|
|
open Stdlib0
|
|
let copy_location x = x
|
|
let rec copy_r : In.X.r -> Out.X.r =
|
|
fun { In.X.a = a; In.X.b = b } -> { Out.X.a = a; Out.X.b = b }
|
|
and copy_s : In.Y.s -> Out.Y.s =
|
|
function | In.Y.A x0 -> Out.Y.A x0 | In.Y.B x0 -> Out.Y.B x0
|
|
|
|
Note that it just copies the base types (string, int, etc...) directly and does
|
|
not expect a copy_string function.
|
|
|
|
================= Recursive types ===============
|
|
|
|
Recursive types should be handled properly:
|
|
|
|
$ cat > in.ml << EOF
|
|
> module X = struct
|
|
> type a = b list
|
|
> and b = A of a | B
|
|
> end
|
|
> EOF
|
|
|
|
$ ../../dev/gencopy/gencopy.exe in.ml out.ml
|
|
open Stdlib0
|
|
let copy_location x = x
|
|
let rec copy_a : In.X.a -> Out.X.a = fun x -> List.map copy_b x
|
|
and copy_b : In.X.b -> Out.X.b =
|
|
function | In.X.A x0 -> Out.X.A (copy_a x0) | In.X.B -> Out.X.B
|
|
|
|
Any type it encounters a non base type, it assumes that a copy_ function
|
|
for this type will be defined. If the type is defined in the input file, it
|
|
should generate it itself, otherwise it will have to be added manually.
|
|
|
|
================= Parametrized types ===============
|
|
|
|
A copy_function for a parametrized type should be polymorphic and take
|
|
one extra argument per type parameter. It should also properly pass that
|
|
argument when copying instances of a parametrized type.
|
|
|
|
$ cat > in.ml << EOF
|
|
> module X = struct
|
|
> type 'a loc = { loc: location; txt: 'a }
|
|
> and u = A | B
|
|
> and v = { u : u loc; flags : int }
|
|
> end
|
|
> EOF
|
|
|
|
$ ../../dev/gencopy/gencopy.exe in.ml out.ml
|
|
open Stdlib0
|
|
let copy_location x = x
|
|
let rec copy_loc : 'f0 'g0 . ('f0 -> 'g0) -> 'f0 In.X.loc -> 'g0 Out.X.loc =
|
|
fun f0 { In.X.loc = loc; In.X.txt = txt } ->
|
|
{ Out.X.loc = (copy_location loc); Out.X.txt = (f0 txt) }
|
|
and copy_u : In.X.u -> Out.X.u =
|
|
function | In.X.A -> Out.X.A | In.X.B -> Out.X.B
|
|
and copy_v : In.X.v -> Out.X.v =
|
|
fun { In.X.u = u; In.X.flags = flags } ->
|
|
{ Out.X.u = (copy_loc copy_u u); Out.X.flags = flags }
|
|
|
|
=================== Inline records =================
|
|
|
|
Inline record fields should not be qualified (e.g. Modname.fiel_name) as this
|
|
would trigger a compile error. gencopy should properly handle this:
|
|
|
|
$ cat > in.ml << EOF
|
|
> module X = struct
|
|
> type x =
|
|
> | A of {i: int; s: string}
|
|
> end
|
|
> EOF
|
|
|
|
$ ../../dev/gencopy/gencopy.exe in.ml out.ml
|
|
open Stdlib0
|
|
let copy_location x = x
|
|
let rec copy_x : In.X.x -> Out.X.x =
|
|
function | In.X.A { i; s } -> Out.X.A { i; s }
|
|
|
|
====================== X.t as x ====================
|
|
|
|
For convenience, gencopy the copy function for X.t as copy_x:
|
|
|
|
$ cat > in.ml << EOF
|
|
> module X = struct
|
|
> type t = int
|
|
> end
|
|
> EOF
|
|
|
|
$ ../../dev/gencopy/gencopy.exe in.ml out.ml
|
|
open Stdlib0
|
|
let copy_location x = x
|
|
let rec copy_x : In.X.t -> Out.X.t = fun x -> x
|
|
|