package GT

  1. Overview
  2. Docs
Generic programming with extensible transformations

Install

Dune Dependency

Authors

Maintainers

Sources

v0.5.4.tar.gz
sha256=d379da5902e2f4017122daf4861dd4f822a862025e9a6d215454ced572da13db
sha512=fe5cb5306cf220f293c0f81b57a8de90f932d3145538e0a032f4b90b8b465ba5d9414692c194b6213014ee2cd06ce061df4541533550d89c7f63b071015104ba

Description

Yet another library for generic programming. Provides syntax extensions both for camlp5 and PPX which allow decoration of type declarations with following compile-time code generation. Provides the way for creating plugins (compiled separately from the library) for enchancing supported type transformations.

Strongly reminds the visitors library from François Pottier. During desing of a library of these kind there many possible design decision and in many cases we decided to implement the decision opposite to the one used in visitors.

P.S. Since 2023 development team is no longer associated with JetBrains Research

Published: 26 Mar 2025

README

GT" GT" License" API docs"

Coverage Status"

Datatype-generic object-oriented transformations for OCaml (a.k.a. GT)

This library implements a framework for datatype-generic programming in Objective Caml language.

The key feature of the approach in question is object-oriented representation of transformations performed over regular algebraic datatypes. Our implementation supports polymorphic variants; in particular, a transformation for a "joined" polymorphic variant type can be acquired via inheritance from the transformations for its counterparts.

See also

visitors

BAP's vistors

Janestreet's PPX Traverse

Installation

opam pin add GT https://github.com/PLTools/GT.git -y

or from the main opam repository

    opam update
opam install GT -y

Usage

As PPX

Use findlib package GT.ppx in combination with ppxlib. See ppxlib's manual for full guidance. In short do

# #use "topfind";;
# #require "GT";;
# #require "GT.ppx_all";;
../GT/ppx_all: added to search path
../GT/ppx_all/./ppx.exe --as-ppx: activated
# type 'a list = Nil | Cons of 'a * 'a list [@@deriving gt ~options:{fmt; show}];;
type 'a list = Nil | Cons of 'a * 'a list
class virtual ['ia, 'a, 'sa, 'inh, 'extra, 'syn] list_t :
  object
    method virtual c_Cons : 'inh -> 'extra -> 'a -> 'a list -> 'syn
    method virtual c_Nil : 'inh -> 'extra -> 'syn
  end
val gcata_list :
  ('a, 'typ0__003_, 'b, 'c, 'typ0__003_ list, 'd) #list_t ->
  'c -> 'typ0__003_ list -> 'd = <fun>
class ['a, 'b] show_list_t :
  (unit -> 'a -> string) ->
  (unit -> 'a list -> string) ->
  object
    constraint 'b = 'a list
    method c_Cons : unit -> 'a list -> 'a -> 'a list -> string
    method c_Nil : unit -> 'a list -> string
  end
class ['a, 'b] fmt_list_t :
  (Format.formatter -> 'a -> unit) ->
  (Format.formatter -> 'a list -> unit) ->
  object
    constraint 'b = 'a list
    method c_Cons : Format.formatter -> 'a list -> 'a -> 'a list -> unit
    method c_Nil : Format.formatter -> 'a list -> unit
  end
val fmt_list :
  (Format.formatter -> 'a -> unit) -> Format.formatter -> 'a list -> unit =
  <fun>
val list :
  (('a, 'b, 'c, 'd, 'b list, 'e) #list_t -> 'd -> 'b list -> 'e,
   < fmt : (Format.formatter -> 'f -> unit) ->
           Format.formatter -> 'f list -> unit;
     show : ('g -> string) -> 'g list -> string >,
   (('h -> 'i list -> 'j) -> ('k, 'i, 'l, 'h, 'i list, 'j) #list_t) ->
   'h -> 'i list -> 'j)
  GT.t = {GT.gcata = <fun>; plugins = <obj>; fix = <fun>}
val show_list : ('a -> string) -> 'a list -> string = <fun>

As Camlp5 syntax extension

Use findlib package GT.syntax.all to enable extension and all built-in plugins. To compile and see the generated code use the following command:

ocamlfind opt -syntax camlp5o -package GT.syntax.all regression/test081llist.ml -dsource

To preprocess only the code in this library (for example, a test) use the following shell command:

dune exec camlp5/pp5+gt+plugins+o.exe regression/test005.ml

To use camlp5 (>= 7.12) syntax extension in toplevel try (after installation) this:

# #use "topfind.camlp5";;
# #camlp5o;;
# #require "GT.syntax";;
# #require "GT.syntax.all";;
# @type t = GT.int with gmap,show;; (* for example *)

Directory structure

  • The framework for generation is in common/. The generic plugin for adding new transformations is in common/plugin.ml.
  • All built-in plugins live in plugins/ and depend on the stuff in common/.
  • Camlp5-specific preprocessing plugin lives in camlp5/. Depend on stuff in common/.
  • PPX-specific preprocessing plugin lives in ppx/. Depends on stuff in common/.
  • Built-in plugins that represent transformations live in plugins/. Depends on common/.
  • A library for built-in types and transformations for types from Pervasives live in src/. Depends on syntax extension from camlp5/ and plugins from plugins/.

Dependencies

  • ppxlib
  • camlp5
  • ocamlgraph for topological sorting
  • ocamlbuild as build system

Compilation

  • make to compile whole library.
  • make && make tests to compile regression tests too.

In case some of the tests do not compile use following commands to see generated code:

  • with camlp5 use dune exec camlp5/pp5+gt+plugins+o.exe regression/test817logic.ml
  • with PPX use dune exec ppx/pp_gt.exe regression/test801mutal.ml

To build documentation set the environment variable GT_WITH_DOCS and run opam install odoc --yes && dune build @doc. The generated HTML files will be located at _build/default/_doc/_html/index.html.

In the following section we describe our approach in a nutshell by a typical example.

Limitations

Known to be not supported or not taken to account:

  • non-regular recursive types
  • GADTs

TODO

Can be a bug:

  • Method on_record_declaration doesn't introduce new pattern names systematically
  • For compare and eq plugins in case of ADT with single constructor we generate unreachable pattern matching pattern that gives a warning.

Improvements:

  • Documentation for src/GT.ml is not generated (possible because of a macro).
  • Better signature for method virtual on_record_constr.
  • Custom transformation functions for type parameters has become broken after introducing combinatorial interface for type abbreviations.
  • Allow [@@named "..."] attribute to provide a custom name for non-latin constructors (like lists).
  • Sometimes we need override class definition for a plugin. It should be possible to specify new custom class inside the attribute.

References

Dependencies (11)

  1. conf-m4 build
  2. bisect_ppx build
  3. logger-p5 build
  4. ocamlfind build
  5. ppx_inline_test_nobase
  6. ocamlgraph
  7. camlp5 >= "8.00.05"
  8. ppxlib <= "0.34.0"
  9. dune-configurator
  10. dune >= "3.16"
  11. ocaml >= "4.14" & < "5.0.0" | >= "5.3.0" & < "5.4.0"

Dev Dependencies (4)

  1. mdx with-test
  2. pa_ppx with-doc
  3. odig with-doc
  4. odoc with-doc

Used by (4)

  1. noCanren
  2. OCanren >= "0.3.0~alpha1"
  3. OCanren-ppx = "0.3.0~alpha1"
  4. ostap

Conflicts

None

OCaml

Innovation. Community. Security.