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

Parsing and basic checking for abstract class and base class. #3385

Merged
merged 11 commits into from
Nov 13, 2023

Conversation

zygoloid
Copy link
Contributor

For now, we require the same introducer to be used each time a class is declared, but see #3384.

if (class_info.inheritance_kind == SemIR::Class::Abstract) {
CARBON_DIAGNOSTIC(ConstructionOfAbstractClass, Error,
"Cannot construct instance of abstract class `{0}`. "
"Consider using `partial` class type instead.",
Copy link
Contributor

Choose a reason for hiding this comment

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

class type -> facet?

https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/classes.md#partial-facet

Suggested change
"Consider using `partial` class type instead.",
"Consider using `partial` facet type instead.",

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@josh11b I think that's out of date; we use "facet" to mean a value of facet type these days, and it seems confusing to also use it here. (It wouldn't be wrong, because every type is a facet, because type is a facet type, but it seems at least misleading.)

Copy link
Contributor

Choose a reason for hiding this comment

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

I agree that we've changed how we use the word "facet" since https://github.com/carbon-language/carbon-lang/blob/trunk/docs/design/classes.md#partial-facet was written. I don't have a good replacement term at the moment. "partial class type" would be fine with me until we have that discussion, though should it be "partial-class type"?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I'm trying to suggest specifically using the partial keyword here. I suppose we could use

                      "Cannot construct instance of abstract class. "
                      "Consider using `partial {0}` instead.",

Thoughts, preferences?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I've switched to the partial {0} approach for now.

Copy link
Contributor

Choose a reason for hiding this comment

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

I could go either way on this; I think the change is fine to keep.

// result in a `set_packaging_state` call. Note, this may not always be
// necessary but is probably cheaper than validating.
switch (position_kind) {
case Lex::TokenKind::Abstract: {
Copy link
Contributor

Choose a reason for hiding this comment

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

What would you think of pushing abstract and base handling out of this file, and into their own state? That way, the general declaration scope handling doesn't start to become specialized towards handling specific syntaxes, which would make the file scale up in size. Perhaps that would also allow for aa setup that didn't need to change the handling of interface or class in this file, allowing Consume to continue to be done locally within handlers.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I tried that first, but ended up with lots of extra states that seemed to be making the parsing more complicated. Maybe we can take another look as a follow-up?

One thing I have in the back of my mind here is what this will look like once we handle more modifiers: I've been imagining that we'd (effectively) have a loop consuming them until it hits an introducer, and then producing the introducer node followed by the modifiers (in their original order). And I think that doesn't easily fall out of a stack-based approach: the stack would reverse the order of modifiers, and we'll want to push an introducer-specific state to parse the rest of whatever we found which should be run after we add the modifier nodes, requiring pushing to somewhere that's not the top of the stack. It seems to me like using the state stack to model that would require that we do some mutation and/or reordering of the stack once we hit the introducer. Maybe that's OK though? We already do something like that for tuples.

Another possibility would be to do lookahead from the start of a declaration to find the introducer token, and enter the right state for it and immediately build its parse node. Then, it can handle its own modifiers in whatever way makes sense, and just skip the introducer token once it's reached. (We'd effectively be parsing as if we first reordered public abstract class X to class public abstract X.)

In any case, I'd prefer to dig into this in a separate PR, once we have more modifiers that we need to support, if that works for you?

Copy link
Contributor

Choose a reason for hiding this comment

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

I'm a little wary here, particularly due to the addition of peeking in PositionIs and PositionKind to support something that I think should be removed. We can proceed, but can you add a TODO to those functions to suggest avoiding/removing the depth argument if possible?

toolchain/parse/handle_declaration_scope_loop.cpp Outdated Show resolved Hide resolved
toolchain/check/handle_class.cpp Outdated Show resolved Hide resolved
Copy link
Contributor

@jonmeow jonmeow left a comment

Choose a reason for hiding this comment

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

Approving, hopefully the related #toolchain discussion yields a good improvement.

@zygoloid zygoloid added this pull request to the merge queue Nov 13, 2023
Merged via the queue into carbon-language:trunk with commit 2715e22 Nov 13, 2023
6 checks passed
@zygoloid zygoloid deleted the toolchain-base branch November 13, 2023 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants