A workaround to print ## as it is, not as a infix operator.
Closed this issue · 4 comments
Taken from here
Eg. obj##foo will be translated to (## obj foo) when I invoke ppx_deriving as a command line tool (compiled by myself). I understand ## is not standard object dispatch but is it possible that we keep it as it is, and not transform it?
Thanks!
Best,
Bob
ocaml-migrate-parsetree does not do parsing nor printing.
The best that can be done to handle your case in the long term is to ask for '#' to be properly handled as an infix operator in:
https://github.com/ocaml/ocaml/blob/trunk/parsing/pprintast.ml#L32 (or eventually to have a specialized printing rule in https://github.com/ocaml/ocaml/blob/trunk/parsing/pprintast.ml#L526).
I am afraid this will take a lot of time. In the meantime, you can probably do a transform your self to turn '##' back to method application (valid only before printing, don't use the AST for anything else):
open Asttypes
open Parsetree
open Ast_mapper
let is_sharpop = function
| Longident.Lident str -> String.length str > 1 && str.[0] = '#'
| _ -> false
let is_ident = function
| Longident.Lident _ -> true
| _ -> false
let extract_sharpop = function
| Longident.Lident str -> String.sub str 1 (String.length str - 1)
| _ -> assert false
let extract_ident = function
| Longident.Lident str -> str
| _ -> assert false
let sharpop_mapper =
let expr mapper (expr : expression) =
match expr.pexp_desc with
| Pexp_apply ({ pexp_desc = Pexp_ident {txt = op; _}; pexp_loc;
pexp_attributes=[]; _},
[(Nolabel, head); (Nolabel, { pexp_desc = Pexp_ident {txt = msg; _}; pexp_attributes=[]; _})])
when is_sharpop op ->
let op = extract_sharpop op in
let msg = extract_ident msg in
let head = mapper.expr mapper head in
{expr with pexp_desc = Pexp_send (head, op ^ msg)}
| _ -> default_mapper.expr mapper expr
in
{default_mapper with expr}
Which is a workaround:
# let expr = Parse.expression (Lexing.from_string "x##a b c");;
# Format.printf "%a\n" Format.std_formatter expr;;
(## x a) b c
- : unit = ()
# Format.printf "%a\n" Pprintast.expression (sharpop_mapper.Ast_mapper.expr sharpop_mapper expr);;
x##a b c
- : unit = ()
Will changing how OCaml compiler even work? By looking at the code
let infix_symbols = [ '='; '<'; '>'; '@'; '^'; '|'; '&'; '+'; '-'; '*'; '/';
'$'; '%' ]
The infix_symobls
are all defined as one character, but in my case I need to handle ##
.
No, these are the first characters of infix_symbols.