Skip to content

Latest commit

 

History

History
195 lines (130 loc) · 6.11 KB

File metadata and controls

195 lines (130 loc) · 6.11 KB

Building AST

🔗 Docs

This section has code examples to help you understand it better.
To run the examples:

make demo-building_ast

Table of Contents

Description

Building an AST (Abstract Syntax Tree) is a fundamental part of creating a PPX in OCaml. You'll need to construct an AST to represent the code you want to generate or transform.

For example, if you want to generate the following code:

let zero = [%int 0]

and replace the extension point [%int 0] with 0 to produce let zero = 0, you’ll need to build an AST that represents this transformation.

There are several methods to build an AST. We’ll discuss three approaches:

  • Building ASTs with Pure OCaml
  • Building ASTs with AST_builder
  • Using Metaquot for AST Construction

Building ASTs with Low-Level Builders

The most fundamental way to build an AST is to manually construct it using Low-Level Builders data structures.

Example: Building a Simple Integer AST Manually

🔗 Sample Code

To construct an AST for a simple integer value 0:

let zero ~loc : Ppxlib_ast.Ast.expression =
  {
    pexp_desc = Pexp_constant (Pconst_integer ("0", None));
    pexp_loc = loc;
    pexp_loc_stack = [];
    pexp_attributes = [];
  }

While this method provides full control over the AST, it is verbose and less maintainable.

Building ASTs with AST_builder

PPXLib provides the AST_builder module, which simplifies the process of building ASTs by providing helper functions.

Example 1: Using pexp_constant for Integer AST

🔗 Sample Code

Using pexp_constant, you can construct an integer AST like this:

let one ~loc =
  Ast_builder.Default.pexp_constant ~loc (Parsetree.Pconst_integer ("1", None))

This method is more readable and concise compared to the pure OCaml approach.

Example 2: Using eint for Simplified Integer AST

🔗 Sample Code

For even more simplicity, use eint:

let two ~loc = Ast_builder.Default.eint ~loc 2

💡 Tip
eint is an abbreviation for expression (e) integer (int).

Using Metaquot for AST Construction

Metaquot is a syntax extension that allows you to write ASTs in a more natural and readable way.

Example: Building an Integer AST with Metaquot

🔗 Sample Code

With Metaquot, you can construct an integer AST like this:

let three ~loc = [%expr 3]

💡 Tip
Metaquot is highly readable and intuitive but is static. For dynamic values, use Anti-Quotations.

Using Anti-Quotations in Metaquot

Anti-Quotations allow you to insert dynamic expressions into your Metaquot ASTs.

Example: Inserting Dynamic Expressions with Anti-Quotations

🔗 Sample Code

To insert a dynamic expression into a Metaquot AST:

let anti_quotation_expr expr = [%expr 1 + [%e expr]]

For example, to insert the AST for 1:

let _ =
  print_endline
    ("\nLet expression with metaquot and anti-quotation: "
    ^ Astlib.Pprintast.string_of_expression (anti_quotation_expr (one ~loc)))

Building Complex Expressions

Beyond simple expressions, you may need to build more complex ASTs, such as let expressions.

Example 1: Constructing a Let Expression with AST_builder

🔗 Sample Code

To build a let expression that binds the value 3 to the variable foo:

let let_expression =
  let expression =
    Ast_builder.Default.pexp_constant ~loc:Location.none
      (Pconst_integer ("3", None))
  in
  let pattern =
    Ast_builder.Default.ppat_var ~loc:Location.none
      (Ast_builder.Default.Located.mk ~loc:Location.none "foo")
  in
  let let_binding =
    Ast_builder.Default.value_binding ~loc:Location.none ~pat:pattern
      ~expr:expression
  in
  Ast_builder.Default.pexp_let ~loc:Location.none Nonrecursive [ let_binding ]
    (Ast_builder.Default.eunit ~loc:Location.none)

Example 2: Constructing a Let Expression with Metaquot

🔗 Sample Code

Alternatively, with Metaquot:

let let_expression =
  [%expr
    let foo = 3 in
    ()]

This approach is shorter and easier to understand.

Conclusion

In this section, we explored three methods for building ASTs:

  • Pure OCaml: The most basic but verbose approach.
  • Using AST_builder: A more readable and maintainable option.
  • Using Metaquot: The most intuitive method, especially when combined with Anti-Quotations for dynamic values.

Each method has its strengths, so choose the one that best fits your needs. Understanding all three will give you greater flexibility in creating effective and maintainable PPXs.