Skip to content

Interest in effects to replace ~loc #635

@N1ark

Description

@N1ark

Hi! I started using ppxlib quite heavily recently, and it's super useful, thanks! However, I find that having to pass a ~loc to all constructors / having to always have a loc variable in scope is a bit tedious, and sometimes leads to overly verbose code.

In my ppx deriver I defined a tiny wrapper around all constructors that take in a ~loc, and defined a simple algebraic effect to instead store the location without having to make it explicit. The implementation is just this:

open Ppxlib
open Ast_builder.Default

type _ Effect.t += Get_loc : location Effect.t

let with_loc (loc : location) f =
  let open Effect.Deep in
  try f () with effect Get_loc, k -> continue k loc

let get_loc () = Effect.perform Get_loc

let ( let@ ) = ( @@ )

(* Override anything we need *)
let pexp_ident x = pexp_ident ~loc:(get_loc ()) x
let ppat_any () = ppat_any ~loc:(get_loc ())
(* etc ... *)

(* Usage is simple! *)
let@ () = with_loc my_loc in
let my_ident = pexp_ident (Lident "foo") in ...

This allows me to write the ppx without having to worry about locations: I just wrap the top-most element with the location i care about, and optionally re-wrap sub-items if i want a more precise location there. I still need a loc in scope when using the ppx, but that just requires a let loc = get_loc ()

Is this something that would be of interest to other users of ppxlib? I would be happy to open a PR and add this as an optional replacement to Ast_builder.Default. Or does this go completely against the intended use of locations? At least in our codebase this has proven quite useful :)

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions