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
EEP-49: First proof of concept implementation #5216
Conversation
This will make it easier for the judges to understand the project and for us to add specific instructions to help them.
trying my hand at the syntax
…erlang#5) * Make it build, extend type of block * Reuse cr_clauses since its identical to the definition of else_clauses * Fix the missing pass through from normal expr to maybe_expr * Back to 3 tuples for non else clause * Fix maybe_expr value not being a proper list * Fix the abstract block type
) * Do the easy {block,_,_,_} support bits Adds the basic forms to erl_syntax, parse transforms, etc. Ignores the trickier bits, namely: - erl_lint, which we hope to avoid for the parse transform phase - erl_eval, which may reuse a parse transform's code - v3_core, which would have a final non-ptrans handling as well. * actually keep backwards compat on cover * clean up erl_syntax a bit * instructions updated * Erroneously entering this one. * Damn it more garbage * fixing syntax error * fixing syntax error again * fixing bad variables * move from else to catch, causes issues with conditional macros
Variables bound before cond are detected bound in the clauses
Maybes are converted into simple matches with no conditionals
This more complex test seems to show the linter going awry on begin ... cond expressions where a clause can be used but the linter complains it wouldn't be used!
Make things work in v3_core
* Simple trailing maybes without cond work * Works in all corner cases ... once * Make it work more than once * Refactored and simplified * Refactor, fold all corner cases
The previous format caused issues where shared cond clauses injected deeper into the tree could cause the core ssa passes to warn about clauses that would never match. This patch instead uses a single large shared cond clause that uses the union of all possible results to match them. It creates a few intermediary tagged terms, but fully silences the compiler. Not sure what impact it'd have on Dialyzer warnings.
Hoist conditional flow
Fix history display, erl_eval exception
Without these, the various syntax tools that also support block would have blown up all the time.
Complete syntax support by adding {maybe, _, _, _} exprs
Adapt Emacs indentation
Add Emacs to the README
CI seems to implode due to the github docker packages service being degraded right now. |
@ferd It would be nice to avoid the use of |
The OTP team had a discussion about this last week and we think this is a good suggestion for an language addition but we want the following to be solved:
I suggest that the discussion continues with the EEP-49 as base. Will come with proposals in an updated version of the EEP soon. |
I would have really appreciated that feedback in the three years that EEP-49 was open for review, and even vetted with these keyword choices after rounds of reviews, because they drastically change the implementation and we could have gotten it closer to everything on the first try!
maybe
{ok, Config} <- parse_config(X),
ok <- validate_config(X),
MinSize = get_min_size(Config, DefaultMin)
MaxSize = get_max_size(Config, DefaultMax)
else
{error, _} ->
MinSize = DefaultMin,
MaxSize = DefaultMax
end This sort of approach is currently allowed with {MinSize, MaxSize} =
maybe
Config <- parse_config(X),
ok <- validate_config(X),
{get_min_size(Config, MinDefault),
get_max_size(Config, MaxDefault)}
else
{error, _} -> {MinDefault, MaxDefault}
end They can be equivalent, and I figure that the bottom approach is safer if there because cases like the following would be hard to get right: maybe
{ok, Config} <- parse_config(X),
ok <- validate_config(X),
{ok, MinSize} <- get_min_size(Config)
{ok, MaxSize} <- get_max_size(Config)
else
{error, _} ->
MinSize = DefaultMin,
MaxSize = DefaultMax
end because now a failure on @peerst and I can try and make most of these changes work. Is the expectation that the OTP team would update EEP-49 ("Will come with proposals in an updated version of the EEP soon") or that I should be updating the EEP as well? |
Another alternative to |
Opinion from a new Erlang dev: "reusing operator is a plus"! |
I assume the |
yeah sorry, I reused the values and the two in the else clause should be |
Sorry for the late feedback. We have liked this proposal for quite some time now. Our view of it has matured and now we have looked at it from a different angle + more detailed. That is why we now have some detailed suggestions about the keywords, the export of variables and the operator. Your PR triggered us to have a new meeting about this and now you have got our feedback. We think/hope it would be possible to include this in OTP 25 together with a new mechanism for activating new language features per module. Our plan to make this happen is that we create a new version of the EEP where our suggestions are incorporated and then we have a meeting with @ferd and @peerst where we can agree on the next steps.
Yes it is easy to add
We expect that we will find a solution for using
We think that the export of variables out of a block is a mistake from the beginning and don't want to introduce yet another block with that problem.
Yes we plan to update the EEP and to work with the implementation as well. The tricky thing is to agree on the exact syntax and sematics. Then the implementation should be rather straightforward. |
Thanks for the update. I'll be awaiting your input for the next steps, and will see if I have time to update this PR until then. |
I have now implemented compiler support for EEP 49 in a draft pull request. Differences from the EEP and your implementation are described in the pull request description. |
@ferd Kenneth and I have updated EEP 49 in a pull request to reflect the notes from the OTP Technical Board. Please have a look. |
Already done! Thanks for the heads up. I'll close this PR since it has been superseded. |
That was quick! Thanks!
I haven't implemented support for |
As part of our spawnfest project, @peerst and I spent the week-end setting up the first proof of concept implementation of EEP-49.
What is this?
See the EEP-49, or for a more terse discussion, the README from the Spawnfest repo
Differences from EEP-49
While implementing we figured out that the choice of
else
in EEP-49 was more trouble than expected. Not only would it collide with usage of atomelse
but also with the-else
attribute of epp.So we decided to go with
begin ... cond ... end
instead. Also trying out the alternativebegin ... catch ... end
in not merged PR Switch from 'cond' to 'catch' in maybe clauses. Keywordcond
was always reserved but not used so far andcatch
is used for exceptions but that usage wouldn't collide. We also discussedcond ... catch ... end
which might or might not collide with the initially intendedcond
expression.If the OTP team has a suggestion regarding how to make
else
work without clashing with pre-processor macros, we're all ear. For the rest of it, we feel that this is a decent representation of the EEP.Implementation Details
This branch is forked off
master
branch as recommended by the contributing guides. We have covered the following level of features:case ... of ... end
expressions in the AST, which gets translated to standard core Erlangcond_clause
, similar toif_clause
andcase_clause
exceptionscond
correctly in abegin...end
What we haven't really had the time to check:
The approach we took for the implementation is based on tagging and returning values of the
begin ... cond ... end
construct and transforming them in the first pass of the compiler changing the AST to core format. This test shows the sort of original format vs. the intended transformation:A previous form took the
cond ... end
segment and carried it into every branch as it was simpler and had (we suppose) more limited overhead, but this would end up carrying a general set of clauses that cover the wholebegin ... cond
section and apply them to individudalMaybeExprs
(Pat <- Expr
), and BEAM SSA passes would correctly warn about unreachable clauses. We nevertheless kept this implementation for the shell, since it won't do this type of linting.What do we expect?
At this point, we'd like to drive the discussion forwards for the EEP, having cleared up most of the initial hurdles, to know how to get this ready for OTP-25.