Sophie

Sophie

distrib > Mageia > 7 > armv7hl > media > core-release > by-pkgid > fb18813323b88f9a6e869238ab603257 > files > 517

ocaml-doc-4.07.1-2.mga7.noarch.rpm

<!DOCTYPE html>
<html>
<head>

<meta http-equiv="Content-Type" content="text/html; charset=US-ASCII">
<meta name="generator" content="hevea 2.32">

  <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1">
<link rel="stylesheet" type="text/css" href="manual.css">
<title>Chapter&#XA0;24&#XA0;&#XA0;Compiler plugins</title>
</head>
<body>
<a href="afl-fuzz.html"><img src="previous_motif.svg" alt="Previous"></a>
<a href="index.html"><img src="contents_motif.svg" alt="Up"></a>
<a href="core.html"><img src="next_motif.svg" alt="Next"></a>
<hr>
<h1 class="chapter" id="c:plugins">Chapter&#XA0;24&#XA0;&#XA0;Compiler plugins</h1>
<ul>
<li><a href="plugins.html#sec548">24.1&#XA0;&#XA0;Overview</a>
</li><li><a href="plugins.html#sec549">24.2&#XA0;&#XA0;Basic example</a>
</li></ul>

<h2 class="section" id="sec548">24.1&#XA0;&#XA0;Overview</h2>
<p>Starting from OCaml 4.03, it is possible to extend the native and bytecode compilers
with plugins using the <span class="c003">-plugin</span> command line option of both tools.
This possibility is also available for <span class="c003">ocamldep</span> for OCaml version ulterior to 4.05.
Beware however that plugins are an advanced feature of which the design
is still in flux and breaking changes may happen in the future. Plugins features
are based on the compiler library API. In complement, new hooks have been added to
the compiler to increase its flexibility.</p><p>In particular, hooks are available in the
<a href="libref/Pparse.html"><span class="c003">Pparse</span> module</a>
to transform the parsed abstract syntax tree, providing similar functionality
to extension point based preprocessors.
Other hooks are available to analyze the typed tree in the
<a href="libref/Typemod.html"><span class="c003">Typemod</span> module</a>
after the type-checking phase of the compiler. Since the typed tree relies
on numerous invariants that play a vital part in ulterior phases of the
compiler, it is not possible however to transform the typed tree.
Similarly, the intermediary lambda representation can be modified by using the
hooks provided in the
<a href="libref/Simplif.html"><span class="c003">Simplif</span> module</a>
.
A plugin can also add new options to a tool through the
<span class="c003">Clflags.add_arguments</span> function (see
<a href="libref/Clflags.html"><span class="c003">Clflags</span> module</a>
).</p><p>Plugins are dynamically loaded and need to be compiled in the same mode (i.e.
native or bytecode) that the tool they extend.</p>
<h2 class="section" id="sec549">24.2&#XA0;&#XA0;Basic example</h2>
<p>As an illustration, we shall build a simple <span class="c003">Hello world</span> plugin that adds
a simple statement <span class="c003">print_endline "Hello from:$sourcefile"</span> to a compiled file.</p><p>The simplest way to implement this feature is to modify the abstract syntax
tree. We will therefore add an hooks to the <span class="c003">Pparse.ImplementationHooks</span>.
Since the proposed modification is very basic, we could implement the hook
directly. However, for the sake of this illustration, we use the <span class="c003">Ast_mapper</span>
structure that provides a better path to build more interesting plugins.</p><p>The first step is to build the AST fragment corresponding to the
evaluation of <span class="c003">print_endline</span>:
</p><pre>  let print_endline name =
    let open Ast_helper in
    let print_endline = Exp.ident
    @@ Location.mknoloc @@Longident.Lident "print_endline" in
    let hello = Exp.constant @@ Const.string @@ "Hello from: " ^ name in
    Str.eval @@ Exp.apply print_endline [Asttypes.Nolabel, hello]
</pre><p>Then, we can construct an ast mapper that adds this fragment to the parsed
ast tree.
</p><pre>let add_hello name (mapper:Ast_mapper.mapper) structure =
  let default = Ast_mapper.default_mapper in
  (print_endline name) :: (default.structure default structure)

let ast_mapper name =
  { Ast_mapper.default_mapper with structure = add_hello name }
</pre><p>Once this AST mapper is constructed, we need to convert it to a hook and adds this
hook to the <span class="c003">Pparse.ImplementationsHooks</span>.
</p><pre>let transform hook_info structure =
        let astm = ast_mapper hook_info.Misc.sourcefile in
        astm.structure astm structure

let () = Pparse.ImplementationHooks.add_hook "Hello world hook" transform
</pre><p>The resulting simplistic plugin can then be compiled with
</p><pre>$ ocamlopt -I +compiler-libs -shared plugin.ml -o plugin.cmxs
</pre><p>Compiling other files with this plugin enabled is then as simple as
</p><pre>$ ocamlopt -plugin plugin.cmxs test.ml -o test
</pre>
<hr>
<a href="afl-fuzz.html"><img src="previous_motif.svg" alt="Previous"></a>
<a href="index.html"><img src="contents_motif.svg" alt="Up"></a>
<a href="core.html"><img src="next_motif.svg" alt="Next"></a>
</body>
</html>