Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add json mapper for pp_ast #526

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

pedrobslisboa
Copy link

Description

Add json mapper on pp_ast to improve usage in tools such as AST Explorer.
The idea is to increment the @NathanReb PR #517

@NathanReb, your opinion on how to structure it better is very welcome.
@jchavarri @davesnx thank you for the help.

How

To use it, we just need to pass --json to ppxlib-pp-ast. It works with all other flags, such as --show-attrs and --show-loc.

How to test

  • In this branch build the project
  • Create a test.ml on the root and add some content
  • Run ppxlib-pp-ast test.ml and check the result
  • Run ppxlib-pp-ast --json test.ml and check the result
  • Use others flags to see the result with --json

Copy link
Collaborator

@patricoferris patricoferris left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a quick comment from me, I don't think we would want to add yojson as a dependency of ppxlib for this feature (I might be mistaken).

The implementation uses the lifter to lift values to JSON values (not actually print them, like pp_simple_val does). So I wonder if this couldn't be its own little tool that depends on ppxlib?

One workaround if this were to be merged here would be to add yojson as a dependency for ppxlib-pp-ast and then ppxlib could just return the polymorphic variants that happen to correspond to the Yojson.Safe.t variants?

@NathanReb
Copy link
Collaborator

Yes, as Patrick said, ppxlib should not depend on external libraries as it otherwise prevents them from being able to depend on ppxlib.

The Yojson dependent parts should go into ppxlib-pp-ast or just a seperate tool shipped with ppxlib-tools.

We could add a json lifter to ppxlib but given it's fairly easy to write one this could be done directly in ppxlib-tools.

Did you try to load the resulting JSON into AST explorer? It would be nice to have a working usecase for this before we merge this feature!

@pedrobslisboa
Copy link
Author

@NathanReb Hey ya!

Did you try to load the resulting JSON into AST explorer? It would be nice to have a working usecase for this before we merge this feature!

I've just pushed a PR on astexplorer refmt to add the ppxlib pp_ast working with this json feature: jchavarri/astexplorer-refmt#1
This same feature could be used on ocaml-platform (Which I'm also working on to migrate to pp_ast). This print is a local demo of the extension running with pp_ast and json:
Captura de Tela 2024-12-06 às 18 56 46

About the yojson, I'm working on removing it

@NathanReb
Copy link
Collaborator

That's awesome! Let me know when this is ready for review!

@pedrobslisboa pedrobslisboa force-pushed the feat/pp_ast__json branch 2 times, most recently from ccbaed9 to 03a46a1 Compare December 10, 2024 14:11
Signed-off-by: pedrobslisboa <[email protected]>
Comment on lines +48 to +98
let pp_simple_val_to_json fmt simple_val =
let rec aux indent fmt simple_val =
match simple_val with
| Unit -> Format.fprintf fmt {|"null"|}
| Int i -> Format.fprintf fmt "%d" i
| String s -> Format.fprintf fmt {|"%s"|} s
| Special s -> Format.fprintf fmt {|"%s"|} s
| Bool b -> Format.fprintf fmt "%b" b
| Char c -> Format.fprintf fmt {|"%c"|} c
| Float f -> Format.fprintf fmt "%f" f
| Int32 i32 -> Format.fprintf fmt "%ld" i32
| Int64 i64 -> Format.fprintf fmt "%Ld" i64
| Nativeint ni -> Format.fprintf fmt "%nd" ni
| Array l | Tuple l | List l ->
Format.fprintf fmt "[\n";
List.iteri
~f:(fun i sv ->
if i > 0 then Format.fprintf fmt ",\n";
Format.fprintf fmt "%s" (String.make (indent + 2) ' ');
aux (indent + 2) fmt sv)
l;
Format.fprintf fmt "\n%s]" (String.make indent ' ')
| Record fields ->
Format.fprintf fmt "{\n";
List.iteri
~f:(fun i (k, v) ->
if i > 0 then Format.fprintf fmt ",\n";
Format.fprintf fmt "%s\"%s\": " (String.make (indent + 2) ' ') k;
aux (indent + 2) fmt v)
fields;
Format.fprintf fmt "\n%s}" (String.make indent ' ')
| Constr (cname, []) -> Format.fprintf fmt {|"%s"|} cname
| Constr (cname, [ (Constr (_, _ :: _) as x) ]) ->
Format.fprintf fmt "{\n%s\"%s\": " (String.make (indent + 2) ' ') cname;
aux (indent + 2) fmt x;
Format.fprintf fmt "\n%s}" (String.make indent ' ')
| Constr (cname, [ x ]) ->
Format.fprintf fmt "{\n%s\"%s\": " (String.make (indent + 2) ' ') cname;
aux (indent + 2) fmt x;
Format.fprintf fmt "\n%s}" (String.make indent ' ')
| Constr (cname, l) ->
Format.fprintf fmt "{\n%s\"%s\": [\n" (String.make (indent + 2) ' ') cname;
List.iteri
~f:(fun i sv ->
if i > 0 then Format.fprintf fmt ",\n";
Format.fprintf fmt "%s" (String.make (indent + 4) ' ');
aux (indent + 4) fmt sv)
l;
Format.fprintf fmt "\n%s]\n%s}" (String.make (indent + 2) ' ') (String.make indent ' ')
in
aux 0 fmt simple_val
Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@patricoferris @NathanReb I've just pushed this simple pretty-printing json function to remove the yojson.

One workaround if this were to be merged here would be to add yojson as a dependency for ppxlib-pp-ast and then ppxlib could return the polymorphic variants that happen to correspond to the Yojson.Safe.t variants?

I could let yojson as a ppxlib_pp_ast dep and return the poly-vars to print jsons only at ppxlib_pp_ast or on the usage of Ppxlib.pp_ast, but it looked hacky as we would have the "pretty-printing" not printing the json but return those poly vars.

Another alternative would be ppxlib-tools to have this dependency and pp_ast to use it.

But as it was not hard to create a simple pp for json, I created it. It isn't as pretty as yojson cause we break every array/list/tuple/record line, but it does not feel like a problem right now.

BTW, I tried to follow pp_simple_val way to print, but it had a strange indent structure, and I created this way. If any issue, just let me now.

@pedrobslisboa
Copy link
Author

@NathanReb BTW, I think now it's ready for review

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants