package codept-lib

  1. Overview
  2. Docs

The M2l module (for Module Meta Language) defines the codept AST.

This AST is a restriction of the Ocaml parsetree AST, that can describe all constructions at the module level but have a very simplified view of value (and type) level expressions.

For instance,

module A = struct
  module Inner = struct let f x = x end
end
let x = 1
open A
module B = struct let y = Inner.f x end

is translated to

module A = struct
  module Inner = struct end
end
open A
module B = struct [%access {Inner}]  end

Main types

type 'a bind = {
  1. name : Name.t option;
  2. expr : 'a;
}

'a bind is an auxilliary type used for module/module type binding

type kind =
  1. | Structure
  2. | Signature
    (*

    The nature (ml/mli) of an m2l ast

    *)
type m2l = expression Loc.ext list

An m2l ast/code fragment is a list of module level expression

and expression =
  1. | Open of module_expr
    (*

    open A.B.COpen [A;B;C]

    *)
  2. | Include of module_expr
    (*

    struct include A end

    *)
  3. | SigInclude of module_type
    (*

    struct include A end

    *)
  4. | Bind of module_expr bind
    (*

    struct module A = struct … end

    *)
  5. | Bind_sig of module_type bind
    (*

    struct module type A = sig … end

    *)
  6. | Bind_rec of module_expr bind list
    (*

    module rec A = … and B = … and …

    *)
  7. | Minor of minor list
    (*

    value level expression. Invariant: for any pure outliner f, f (Minor m :: q ) ≡ f q , i.e, this expression constructor is only meaningful for dependencies tracking.

    *)
  8. | Extension_node of extension
    (*

    [%ext …]

    *)

The expression type is the basic building block of the m2l AST

and minor =
  1. | Access of access
    (*

    see access below

    *)
  2. | Pack of module_expr Loc.ext
    (*

    (module struct ... end)

    *)
  3. | Extension_node of extension Loc.ext
    (*

    %ext ...

    *)
  4. | Local_open of Loc.t * module_expr * minor list
    (*

    let open struct ... end in ...

    *)
  5. | Local_bind of Loc.t * module_expr bind * minor list
    (*

    let module M = ... in ...

    *)

A minor element represents a short description of type or value level constructions, that contains only the information relevant for dependency tracking.

and access = (Loc.t * Deps.Edge.t) Paths.E.map

M.N.L.x ⇒ access {M.N.L = Normal } type t = A.t ⇒ access { A = ε }

and module_expr =
  1. | Ident of Paths.Simple.t
    (*

    A.B… *

    *)
  2. | Apply of {
    1. f : module_expr;
    2. x : module_expr;
    }
    (*

    F(X)

    *)
  3. | Fun of module_expr fn
    (*

    functor (X:S) -> M

    *)
  4. | Constraint of module_expr * module_type
    (*

    M:S

    *)
  5. | Str of m2l
    (*

    struct … end

    *)
  6. | Val of minor list
    (*

    val …

    *)
  7. | Extension_node of extension
    (*

    [%ext …]

    *)
  8. | Abstract
    (*

    empty module expression, used as a placeholder. In particular, it is useful for constraining first class module unpacking as Constraint(Abstract, signature).

    *)
  9. | Unpacked
    (*

    (module M)

    *)
  10. | Open_me of {
    1. opens : Paths.Simple.t Loc.ext list;
    2. expr : module_expr;
    }
    (*

    M.(…N.( module_expr)…) Note: This construction does not exist (yet?) in OCaml proper. It is used here to simplify the interaction between pattern open and first class module.

    *)
  11. | Proj of {
    1. me : module_expr;
    2. proj : Paths.Simple.t;
    }

Module level expression representation

and module_type =
  1. | Alias of Paths.Simple.t
    (*

    module m = A…

    *)
  2. | Ident of Paths.Expr.t
    (*

    module M : F(X).s Note: Paths.Expr is used due to F.(X).s expressions that do not have an equivalent on the module level

    *)
  3. | Sig of m2l
    (*

    sig … end

    *)
  4. | Fun of module_type fn
    (*

    functor (X:S) → M

    *)
  5. | Of of module_expr
    (*

    module type of …

    *)
  6. | Extension_node of extension
    (*

    %%…

    *)
  7. | Abstract
    (*

    module type T

    *)
  8. | With of {
    1. body : module_type;
    2. with_constraints : with_constraint list;
    }
    (*

    S with ...

    *)

Module type level representation

and with_constraint = {
  1. lhs : Paths.S.t;
  2. delete : bool;
  3. rhs : with_rhs;
}
and with_rhs =
  1. | Type of minor list
    (*

    S with type t =/:= ...

    *)
  2. | Module of Paths.S.t Loc.ext
    (*

    S with module N.M := … we need to track abstract module type strenghthening.

    *)
  3. | Module_type of module_type
and 'a fn = {
  1. arg : module_type Module.Arg.t option;
  2. body : 'a;
}

Functor auxiliary type

and extension = {
  1. name : string;
  2. extension : extension_core;
}

An specific represention for an extension node

and extension_core =
  1. | Module of m2l
  2. | Val of minor list

A type for extension payload

type t = m2l
val sch : m2l Schematic.t

Schematic serialization

module Sch : sig ... end
module Annot : sig ... end
module Build : sig ... end

Basis analysis

module Sig_only : sig ... end

Printers

val pp : Format.formatter -> m2l -> unit
val pp_expression : Format.formatter -> expression -> unit
val pp_annot : Format.formatter -> minor list -> unit
val pp_me : Format.formatter -> module_expr -> unit
val pp_mt : Format.formatter -> module_type -> unit
val pp_with_constraints : Format.formatter -> with_constraint list -> unit
val pp_access : access Pp.t
OCaml

Innovation. Community. Security.