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

Refactor json macro #12391

Merged
merged 20 commits into from
Oct 17, 2019
Merged

Refactor json macro #12391

merged 20 commits into from
Oct 17, 2019

Conversation

krux02
Copy link
Contributor

@krux02 krux02 commented Oct 8, 2019

Refactor json to macro, it is now based on overloading. I did this because I wanted to fix #12316 and saw that it was a structural problem of the to macro. Basically this is a big cleanup.

  • Many helper procs, such as createJsonIndexer, getEnum, toIdentNode or workaroundMacroNone became obsolete and have been removed.
  • All post processing to do "fixes" (e.g. postProcess) are gone. It is now all a signle pass.
  • No special code has been written in order to fix json.to fails with ref Bar #12316, code like that just works now.
  • In the old macro, case objects with subbranches didn't work. That has been addressed.
  • Recursive ref types now just work without any problem.
  • There should be a performance increase, because long expressions such as if cond(jsonNode["fieldA"]["fieldB"]["kind"]): doSometing(jsonNode["fieldA"]["fieldB"]["kind"]) are not generated like this anymore. But I didn't measure it.
  • The TODO "Would be good to verify that this is Option[T] from options module" has been addressed
  • Much less and simpler code should be easier to maintain in the future.
  • fixed forward declarations don't work for constrained generic procs #12416 (I had to otherwise it would not compile)
  • fixed nim-gdb.py for the double underscore change.

@krux02 krux02 requested a review from dom96 October 8, 2019 23:07
@krux02
Copy link
Contributor Author

krux02 commented Oct 8, 2019

@dom96: Since it was mostly you who wrote the json macro, I would like to hear your opinion about these chages first from you. I removed most of it, but the test cases stood the same for the most part.

@planetis-m
Copy link
Contributor

Good one! What was the reason you picked overloading over a typed macro?

@krux02
Copy link
Contributor Author

krux02 commented Oct 9, 2019

@B3liever well, to be precise, I did use typed macros. You probably ask why I replaced the logic to select the deserializer with overload resolution. And the short answer is, because it is much simpler to implement. I saw quite some complicated logic in the old macro to detect types based on names and other patterns. And they were almost correct bot not entirely correct and there could be corner cases that nobody thought about that would just not work. And while I was thinking about how to implement this, I also thought: "Hey, we have a correct type matching mechanism in the language, it is called overload resolution". So eventually I decided to throw this weird and complicated logic all away and replace it with something where I know that it works. It turned out to work quite well.

@Vindaar
Copy link
Contributor

Vindaar commented Oct 10, 2019

This is great, thanks!
I wondered before why the to macro didn't work like this in the first place.

This should help with things like https://github.com/nim-lang/Nim/pull/11416/files I believe.

@planetis-m
Copy link
Contributor

planetis-m commented Oct 10, 2019

Hey perhaps you can play with this to macro and see for yourself that typed macros are not unreliable just because the previous to macro had faulty logic.

Also since you already use macros in order to support object variants you must already know that overload resolution doesn't magically work in all cases.

@krux02
Copy link
Contributor Author

krux02 commented Oct 11, 2019

Well, I know there are problems with overload resolution, but I don't think it will be a problem with this specific setup.

Btw nice work on your to macro. Avoiding the intermediate node tree structure is a great optimization. There are some remarks though:

  • Why are you moving the key out of the parser? This mean that the parser will have to reallocate its a member. This will cause an allocation after every key that you parse. You should not do this, better branch directly on the value in place: case p.a, and then put the discard getTok(p); eat(p, tkColon) at the beginning of every of branch.

  • Generating the serializer in place including all sub fields does not allow to deserialize Nodes that contain Nodes (e.g. binary trees). With overloads for each type like I did it here, this is possible.

  • One of the major pain points is to resolve type aliases and to deal with distinct types and the mess it causes. When you don't have type aliases everything is fine, overload resolution helps to deal with this mess.

  • I could not find tests in your library except for a very trivial one. If you don't want to design your own tests, try adapt tests/stdlib/tjsonmacro.nim with your macro. Then you can objectively see how well your implementation supports corner cases.

  • You don't have support for case objects yet. I promise they will become ugly.

@planetis-m
Copy link
Contributor

Thanks for your valuable feedback! I appreciate it, will try to fix some of these issues, when I have time.

@krux02 krux02 force-pushed the refactor-json-macro branch from 87423df to b44bddc Compare October 15, 2019 23:26
@krux02
Copy link
Contributor Author

krux02 commented Oct 16, 2019

This PR is finished now.

lib/pure/json.nim Outdated Show resolved Hide resolved
@@ -1,3 +1,3 @@
Loading Nim Runtime support.
NimEnumPrinter: lookup global symbol 'NTI_z9cu80OJCfNgw9bUdzn5ZEzw_ failed for tyEnum_MyOtherEnum_z9cu80OJCfNgw9bUdzn5ZEzw.
Copy link
Contributor

Choose a reason for hiding this comment

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

Why does this JSON PR have changes to gdb?

Copy link
Contributor Author

@krux02 krux02 Oct 18, 2019

Choose a reason for hiding this comment

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

Yea I know it isn't clean. But I used gdb and fixed it along the way. Then I was too lazy to split the PR up into different parts as the changes in gdb and json were interleaved.

Edit: Btw your review comes a little bit too late. This PR is already merged.

alehander92 pushed a commit to alehander92/Nim that referenced this pull request Dec 2, 2019
* closes nim-lang#12316
* make tjsonmacro work at js target
* closes nim-lang#12289
* closes nim-lang#11988
* also fixed gdb related stuff
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.

forward declarations don't work for constrained generic procs json.to fails with ref Bar
5 participants