-
Notifications
You must be signed in to change notification settings - Fork 43
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
Investigate 'visitors' and 'alphalib' for building SugarTraversals? #255
Comments
We should do this for 0.8. |
Hi! |
Large portions of the code base depends on the visitors defined in SugarTraversals. To assess whether we want to use these libraries to derive visitors, it may be worthwhile, as a starting point, to use them to define visitors for the backend IR. Contrary to the front-end AST, the back-end IR has only a few (unused) optimisation passes/visitors, meaning that we can rapidly prototype the libraries for the IR. It may relevant for @frank-emrich's work on type checking the IR. |
Yes, that's a good idea, if Frank agrees. If it saves work on the IR, then
we'll have a better idea of strengths/limitations, if not we'll know we
don't want to use it elsewhere.
…--James
On Thu, May 10, 2018, 4:21 PM Daniel Hillerström ***@***.***> wrote:
Large portions of the code base depends on the visitors defined in
SugarTraversals. To assess whether we want to use these libraries to derive
visitors, it may be worthwhile, as a starting point, to use them to define
visitors for the backend IR. Contrary to the front-end AST, the back-end IR
has only a few (unused) optimisation passes/visitors, meaning that we can
rapidly prototype the libraries for the IR. It may relevant for
@frank-emrich <https://github.com/frank-emrich>'s work on type checking
the IR.
—
You are receiving this because you commented.
Reply to this email directly, view it on GitHub
<#255 (comment)>,
or mute the thread
<https://github.com/notifications/unsubscribe-auth/ACMu9c7L5Sa5QpRu3-R3JBuV171ThszLks5txFrigaJpZM4Pampa>
.
|
Frank agrees :) |
I have now had a more detailed look at the visitors library/preprocessor and identified a few problems:
We could try to navigate around this as follows, but neither of these solutions seems desirable to me:
|
Hello @frank-emrich! Concerning (1), you are correct: I have not implemented support for polymorphic variants in Concerning (2), you are also correct, that is, the auto-generated visitor classes are just code. They are intended to appear in an |
Thanks for your help, @fpottier! Regarding (2): Your idea of "copying" (using ppx_import) existing type definitions into a dedicated file to create the visitor there sounds very nice and much better than my workarounds above. Thanks for that! |
I think we have decided not to try to do this for 0.8 so untagging for now. |
After further investigation by @jstolarek it seems that we are making use of polymorphic variants in nontrivial (or at least hard-to-remove) ways, so we can't easily migrate to using ordinary datatypes or alphalib/visitors. While it still might make sense for the IR, the real benefit would be auto-generating the much larger traversals for the front-end ASTs. We could revisit this at some point. |
I think it is only true for type algebra in types.ml. I don't think that it is the case for the term algebra sugartypes.ml. Nevertheless, it might be a tedious task to migrate the code. Incidentally, I would be interested in whether there is any practical compile-time performance gain from using ordinary variant types -- in theory there is, as the compiler can use clever decision tree encodings of match expressions. We have previously discussed whether we should collapse the type algebra into a single monolithic algebra. I think it is worth revisiting this idea. In doing so, we could opt to use ordinary variant types, and then we could use Pottier's visitor library to generate all the boilerplate code. |
sugartypes.ml has some benignly-looking data types like: type location = [`Client | `Server | `Native | `Unknown]
[@@deriving show]
type restriction = [ `Any | `Base | `Session | `Effect ]
[@@deriving eq,show]
type linearity = [ `Any | `Unl ]
[@@deriving eq,show]
type freedom = [`Flexible | `Rigid]
[@@deriving show]
type primary_kind = [`Type | `Row | `Presence]
[@@deriving show]
type fieldconstraint = [ `Readonly | `Default ]
[@@deriving show] IIRC I started my attempts of refactoring with
It might be a simple refactoring for someone more experienced with OCaml and with better familiarity of Links source code. But it wasn't simple for me. |
I have played around with the visitors library once again to see if Janek's work on removing polymorphic variants has enabled us to use it. No support for our style of accumulation via the visiting objectOne major obstacle that would prevent us from porting our existing traversals based on
Similarly, in the
However, the visitors library has no support for this kind of traversal, where either the updated object or some "accumulator" is returned from each sub-traversal and passed to the next. The library does offer a different style of generated folds and also a "reducing" traversal, but I assume that it would require a lot of effort to adapt all of our existing traversals to this style. Naming conventionsThe visitors library makes fewer hard-coded assumptions about how things should be named. This means that we need to provide many annotations to specify names and where to look for other visitors.
In summary, this results in a load of syntactic noise. For example
becomes
We may however find a solution for moving these noisy annotations into dedicated files by using |
The second problem doesn't seem so bad, if it means replacing hundreds lines of boilerplate with tens of lines of boilerplate. For the first problem, so how does |
Mutual state is one solution, indeed. Another related solution is a "reduce" visitor, which would yield code similar to this:
where plus is a dedicated combination method that one must implement. Note that this does something slightly different, as it doesn't pass the result of the first sub-traversal to the second one. The generated code always passes an environment around, but again not in the "accumulating" fashion we currently have in In any case, I assume that we could express each of the traversals we currently have in terms of one generated by the visitors library. However, I'm worried that this would be more of a careful re-write rather than quickly applying a series of straightforward modifications to our existing code. Simply because there is no generated drop-in replacement for the exact structure of traversals we currently have. |
If you need to accumulate state during a traversal, then either the visitor object or the environment should be made mutable. So far, I have decided not to generate visitor classes where a state is explicitly threaded, as that would multiply the number of visitor variants, without an obvious gain. |
I can see how the |
Thanks @fpottier ! I think the above comments aren't intended as criticism of |
I think the reduce visitor can simulate a state-threading one by accumulating |
Yes, that should work. It would be a bit inefficient (essentially building a tree of closures whose shape is the same as that of the original tree; therefore doing one tree copy which in principle is not needed). I have published a blog post on a related use of a |
Cool! I think we are already allocating potentially one new object per intermediate state, which is also more inefficient than in-place updates would be (though perhaps most of the "new" states are aliases of the previous one, and maybe the past states can be GCd more eagerly than the tree of closures). I'd rather not have to rewrite a lot of explicit state-passing code to use implicit mutation all at once though, seems like a recipe for introducing hard-to-find bugs... |
The
SugarTraversals
module module was once generated automatically from the datatype definition by a Camlp4 extension. Nowadays it seems to be maintained by hand.It may be worth investigating @fpottier's visitors library for generating visitor classes, and alphaLib library for dealing with binding, which are both described in Visitors Unchained (ICFP 2017), and which support a principled approach to traversing ASTs with binding using modern OCaml tools such as ppx, with the aim of returning to a situation where
SugarTraversals
no longer needs to be updated by hand.The text was updated successfully, but these errors were encountered: