[Main website]

pl/ocaml-extension-points

PPX are executed at compilation phase. They transform the AST of OCaml code.

There are attributes that are attached to the AST, and they are read-only meta-info that does not affect directly compilation and semantic of the PL.

There are extension nodes that are maco instructions that must be expanded to valid OCaml code, from the PPX compiler. TODO check if they can be expanded into code using other extension nodes, like macro in CL.

TODO in Dok I want to add a lot of meta-info to a node, because it supportsfeature/multiple-run-times. So the IDE must mask some of this info. The code is not meant to be readable without an IDE. See paradigm/IDE-oriented-programming.

type serializable_blob = Blob.t =
  { value : string
  ; length : int
  ; id : int
  }
[@@deriving yojson]

let a = 12 [@attr pl]

let b = "some string" [@@attr pl]

[@@@attr pl]


# note: the numbers of @ indicate the scope level at wihch apply the meta-info

# An extension mixing C code with Ocaml code
external%c puts_flush : str:string -> bool = {|
  int r = puts($str);
  if ( r < 0 ){
    return false;
  }
  r = fflush(stdout);
  return (r == 0); /* `return` is mandatory, unless your function is void */
|} [@@ release_runtime_lock]

let _ : bool = puts_flush ~str:"Hello World"

# An extension supporting TDD

let%expect_test _ =
  let f output =
    print_string output;
    [%expect {| hello world |}]
  in
  f "hello world";
  f "hello world";
;;

print blah;
  [%expect {|
abc
defg
  hij|}]

  print blah;
  [%expect {|
                abc
                defg
                  hij
  |}]

  print blah;
  [%expect {|
    abc
    defg
      hij
  |}]

# An extension for SQL

let update_account =
    [%sqlf {|
      UPDATE accounts
         SET email = $email, account_type = $account_type
       WHERE account_id = $account_id
   RETURNING account_id, created_at, account_type, email
    |}]

See http://ocamlverse.net/content/metaprogramming.html as entry point.