Skip to content

Make parser recognize AliasAssign#441

Merged
WebFreak001 merged 2 commits intodlang-community:masterfrom
RazvanN7:AliasAssign
May 20, 2021
Merged

Make parser recognize AliasAssign#441
WebFreak001 merged 2 commits intodlang-community:masterfrom
RazvanN7:AliasAssign

Conversation

@RazvanN7
Copy link
Contributor

@RazvanN7 RazvanN7 commented May 6, 2021

As per: dlang/dmd#11846

A few notes:

  • I have added a new class AliasAssign that is viewed as a declaration so that it could appear in the same context as declarations. This might be a bit hacky, but it seemed like the easiest way to implement this.
  • The AliasAssign class is just a wrapper for AliasInitializer. I considered using an AliasInitializer as that would make the diff smaller, however, that comes with 2 drawbacks: comments cannot be attached to AliasInitializers and it uses AliasInitializer for a purposes that it wasn't designed for. If the maintainers come to the conclusion that it is better to use AliasInitializer, I am open to amend the PR.
  • AliasAssignments should be present only in template declaration contexts, therefore I have added another default parameter to parseDeclaration, so that is signaled to the declaration.

This is currently blocking some PRs in phobos, so if you merge, please also release a new tag so that we can unblock those PRs.

Cheers,
RazvanN

@RazvanN7
Copy link
Contributor Author

RazvanN7 commented May 6, 2021

Test suite is failing with "All tests have passed".

/**
* Parses an AliasAssign.
*
* $(GRAMMAR $(RULEDEF aliasDeclaration):
Copy link
Contributor

Choose a reason for hiding this comment

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

Suggested change
* $(GRAMMAR $(RULEDEF aliasDeclaration):
* $(GRAMMAR $(RULEDEF aliasAssign):

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

Copy link
Member

@WebFreak001 WebFreak001 left a comment

Choose a reason for hiding this comment

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

thanks for the PR! Got some points that should be changed

mixin(traceEnterAndExit!(__FUNCTION__));
auto startIndex = index;
auto node = allocator.make!AliasAssign;
node.initializer = parseAliasInitializer();
Copy link
Member

Choose a reason for hiding this comment

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

AliasInitializer allows adding template parameters, are these really supported by alias assign? (as this is a public function that may be called freely - and for good code style)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Nope. I can implement it properly, but I thought I would just reuse as much code as possible to make the diff smaller.

* ;)
*/
Declaration parseDeclaration(bool strict = false, bool mustBeDeclaration = false)
Declaration parseDeclaration(bool strict = false, bool mustBeDeclaration = false, bool inTemplateDeclaration = false)
Copy link
Member

Choose a reason for hiding this comment

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

are alias assignments only strictly allowed in templates?

Additionally you are missing this parameter in a lot of sub-calls here.

Example that would break as far as I can see:

// parseConditionalDeclaration
static if (true)
{
    A = B;
}

Choose a reason for hiding this comment

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

If I see a static if (true) in there at release I'm gonna burn down Adam's shed

Copy link
Contributor Author

Choose a reason for hiding this comment

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

As far as I could tell from the implementation [1], AliasAssign is allowed only inside template A(..){...} declarations.

I understand your point, however, it is not possible to deduce whether the static if is at function level or at template level during parsing. In dmd, this is checked during semantic analysis, so I assume that the solution for libdparse is to create an AliasAssignDeclaration every time we encounter an assignment that occurs in non-function contexts. ParseDeclaration seems to be called at function scope level also. Any ideas on how I could differentiate between assignments at function level and assignments non-function levels?

[1] https://github.com/dlang/dmd/pull/11846/files?file-filters%5B%5D=.d&file-filters%5B%5D=.h#diff-90e6074482976dda59fff5b12d8aa29f1af3012b5db226a827e8e304b953ec10R6774

Copy link
Member

Choose a reason for hiding this comment

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

I think you want to nest the inTemplateDeclaration parameter into all calls that should keep it, ie. here the parseConditionalDeclaration function and all the other parse*Declaration functions you want to support.

I personally think it would be more pretty doing this with some kind of parse state struct that is passed as argument in all related functions though if this is expected to expand in the future to more edge cases.

Copy link
Contributor Author

@RazvanN7 RazvanN7 May 7, 2021

Choose a reason for hiding this comment

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

I'm not sure this will work. Consider this case:

template X(T)
{
    alias X = int;
    static if (cond)
        X = float;            // this one is currently accepted by dmd
    void fun()
    {
         X = T;               // while this one is not because the assignment
                              // does not have the same parent as the declaration of X
    }
}

This is not going to get solved by passing the inTemplate boolean. Or maybe it could work, but that would mean inserting a primitive form of semantic analysis. Right now, libdparse issues an error when
assignments occur in non-function contexts. If we want to keep things in parser territory, we need to relax that condition and to create AliasAssignDeclarations if an assignment occurs in non-function context. Of course that will allow for code that is not an alias assignment to pass parsing, but that is fine.

Copy link
Member

Choose a reason for hiding this comment

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

the parseFunctionDeclaration body would reset back the boolean value that you are in a template, (implicitly by simply not passing it down as parameter or for a struct explicitly) you will want to do that with anything adding scope.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

hmm, I'll try that out. Thanks for your assistance!

* Parses an AliasAssign.
*
* $(GRAMMAR $(RULEDEF aliasAssign):
* $(RULE aliasInitializer)
Copy link
Member

Choose a reason for hiding this comment

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

this documentation says it would be syntactically valid to use templateParameters in an assignment. As it's never the case that it would actually be valid code I think it would be better to define a proper grammar here.

@RazvanN7
Copy link
Contributor Author

@WebFreak001 @maxhaton I gave it another pass. Kindly asking for a review

Copy link
Member

@WebFreak001 WebFreak001 left a comment

Choose a reason for hiding this comment

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

looks good, just 2 minor things

I think the state passing through parameters is functional and works well with the stack without much overhead, but it might get hard to maintain in case more stuff like this gets added. What does @Hackerpilot think about this? Maybe some explicit push/pop functionality could be considered too? (I think the current way would be the most elegant solution once we have named parameters and not need to write down all the defaults)

mixin(tokenCheck!(`node.identifier`, "identifier"));
mixin(tokenCheck!"=");
mixin (parseNodeQ!(`node.type`, `Type`));
node.tokens = tokens[startIndex .. index];
Copy link
Member

Choose a reason for hiding this comment

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

this line is not needed / covered by attachCommentFromSemicolon

Suggested change
node.tokens = tokens[startIndex .. index];

comment = null;
mixin(tokenCheck!(`node.identifier`, "identifier"));
mixin(tokenCheck!"=");
mixin (parseNodeQ!(`node.type`, `Type`));
Copy link
Member

Choose a reason for hiding this comment

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

and just a style thing because otherwise the PR LGTM :p

Suggested change
mixin (parseNodeQ!(`node.type`, `Type`));
mixin(parseNodeQ!(`node.type`, `Type`));

@maxhaton
Copy link

@RazvanN7 Don't have time to consider this thoroughly but looks good to me for now. Thanks.

@RazvanN7
Copy link
Contributor Author

@WebFreak001 I agree that keeping all the state in one place is easier to maintain, however, at this point that might be an overkill. Anyway, I would rather merge this ASAP to unblock the phobos PRs and refactor later if needed.

@WebFreak001
Copy link
Member

travis fail unrelated

@WebFreak001
Copy link
Member

can't merge because travis is a required check

@RazvanN7
Copy link
Contributor Author

There seems to be a dependency error on stdx.allocator:

../subprojects/stdx-allocator/source/stdx/allocator/internal.d(722): Error: static assert:  `!__traits(compiles, emplace(& s2, 1))` is false

How do we get passed that? Did I mention that this PR is needed to unblock phobos :-" ?

@RazvanN7
Copy link
Contributor Author

RazvanN7 commented May 11, 2021

Ok, so the problem seems to be that libdparse is using an ancient version of stdx.allocator (2.77.5), whereas newer versions don't even contain the assert that is tripping. How do we fix this? Should travis-ci be upgraded somehow or does it suffice to simply change the tag in submodules/stdx-allocator.wrap [1]? I'm gonna try this.

Edit: Hmm, do I have to specifically mention all recursive dependencies? It looks like the problem is that meson does not know how to pull mir-core (that the newer version of stdx.allocator requires).

[1] https://github.com/dlang-community/libdparse/blob/master/subprojects/stdx-allocator.wrap

@RazvanN7 RazvanN7 force-pushed the AliasAssign branch 3 times, most recently from 39cf5ed to 8878047 Compare May 11, 2021 11:51
@RazvanN7
Copy link
Contributor Author

@WebFreak001 I have disabled the meson build as it seemed redundant. Once the dependency issues for meson are fixed, the tests can be un-commented. Is that acceptable?

@codecov
Copy link

codecov bot commented May 20, 2021

Codecov Report

Merging #441 (469bffd) into master (6f0893f) will increase coverage by 0.25%.
The diff coverage is 100.00%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #441      +/-   ##
==========================================
+ Coverage   81.86%   82.12%   +0.25%     
==========================================
  Files          11       11              
  Lines        8454     8463       +9     
==========================================
+ Hits         6921     6950      +29     
+ Misses       1533     1513      -20     
Impacted Files Coverage Δ
src/dparse/ast.d 70.78% <100.00%> (+0.05%) ⬆️
src/dparse/parser.d 91.24% <100.00%> (+0.04%) ⬆️
src/dparse/formatter.d 42.83% <0.00%> (+1.25%) ⬆️
src/std/experimental/lexer.d 86.95% <0.00%> (+2.17%) ⬆️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 6f0893f...469bffd. Read the comment docs.

@RazvanN7
Copy link
Contributor Author

Is this good to go?

@WebFreak001 WebFreak001 merged commit fbdf71b into dlang-community:master May 20, 2021
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.

5 participants

Comments