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

Make the AST mutable #849

Merged
merged 5 commits into from
Sep 27, 2021
Merged

Make the AST mutable #849

merged 5 commits into from
Sep 27, 2021

Conversation

jonmeow
Copy link
Contributor

@jonmeow jonmeow commented Sep 23, 2021

The code is pretty intertwined: having the AST be truly mutable means (to me) changing parser.ypp to return non-const values, but then the way things are passed around between objects should be non-const (particularly an issue with lists), which then creates issues with construction of lists in the TypeChecker, which then TypeChecker needs to mostly be non-const.

Due to the difficulties in breaking this apart, whereas I'd previously considering refactoring accessor naming in the same PR, I've largely avoided doing so. The intent is then that this PR focuses mainly on const -> non-const AST behavior.

call_main moves out of interpreter.cpp so that interpreter.cpp can receive a fully const AST.

@jonmeow jonmeow requested a review from a team as a code owner September 23, 2021 00:08
@google-cla google-cla bot added the cla: yes PR meets CLA requirements according to bot. label Sep 23, 2021
@@ -108,22 +110,21 @@ class ChoiceDeclaration : public Declaration {
}

auto Name() const -> const std::string& { return name; }
auto Alternatives() const -> const
std::vector<std::pair<std::string, Nonnull<const Expression*>>>& {
auto Alternatives() const
Copy link
Contributor

Choose a reason for hiding this comment

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

This is a const method, but it's giving non-const access to the expressions, which I don't think is right. To fix that, I think we'll need to replace std::pair with a proper class with its own const/non-const accessor pair (which IMO we should do anyway). Assuming you don't want to do that in this PR, could we add a TODO, and switch alternatives back to std::vector<std::pair<std::string, Nonnull<const Expression*>>> in the meantime?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doing this in #853

@@ -43,10 +42,10 @@ struct FunctionDefinition {
SourceLocation source_location;
std::string name;
std::vector<GenericBinding> deduced_parameters;
Nonnull<const TuplePattern*> param_pattern;
Nonnull<const Pattern*> return_type;
Nonnull<TuplePattern*> param_pattern;
Copy link
Contributor

Choose a reason for hiding this comment

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

This will allow code holding a const FunctionDefinition* to mutate that definition's parameters. To fix that, I think we'll need to either turn this struct into a class with const/non-const accessors, or wrap the pointer members in something like propagate_const. And unfortunately, I think the same goes for pretty much every pointer member of every struct that this PR touches (but it looks like maybe there aren't too many of those?).

If you don't want to do that in this PR, could we add the const back to those members, and flag it with a TODO?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Switching in #852, that'll block this PR

@@ -248,7 +248,7 @@ auto TypeChecker::Substitute(TypeEnv dict, Nonnull<const Value*> type)
}
}

auto TypeChecker::TypeCheckExp(Nonnull<const Expression*> e, TypeEnv types,
auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
Copy link
Contributor

Choose a reason for hiding this comment

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

What's the rationale for dropping the const here? AFAICT this function doesn't actually need mutable access unless/until we update it to modify the AST in place rather than producing a copy.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Trying to explain on #executable_semantics

Copy link
Contributor

Choose a reason for hiding this comment

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

To recap for future reference, the key issue is that in some circumstances, TypeCheckExp will reuse the input AST node as part of the output. That means in order for the output to be mutable, the input needs to be mutable. I think it's an open question whether that's the right approach long-term, but I think for purposes of this PR, keeping it non-const makes sense.

Copy link
Contributor Author

@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.

Trying to break out related PRs rather than doing class refactorings here, discussing in #executable_semantics

@@ -248,7 +248,7 @@ auto TypeChecker::Substitute(TypeEnv dict, Nonnull<const Value*> type)
}
}

auto TypeChecker::TypeCheckExp(Nonnull<const Expression*> e, TypeEnv types,
auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Trying to explain on #executable_semantics

@@ -43,10 +42,10 @@ struct FunctionDefinition {
SourceLocation source_location;
std::string name;
std::vector<GenericBinding> deduced_parameters;
Nonnull<const TuplePattern*> param_pattern;
Nonnull<const Pattern*> return_type;
Nonnull<TuplePattern*> param_pattern;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Switching in #852, that'll block this PR

@@ -108,22 +110,21 @@ class ChoiceDeclaration : public Declaration {
}

auto Name() const -> const std::string& { return name; }
auto Alternatives() const -> const
std::vector<std::pair<std::string, Nonnull<const Expression*>>>& {
auto Alternatives() const
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Doing this in #853

jonmeow added a commit that referenced this pull request Sep 27, 2021
@@ -248,7 +248,7 @@ auto TypeChecker::Substitute(TypeEnv dict, Nonnull<const Value*> type)
}
}

auto TypeChecker::TypeCheckExp(Nonnull<const Expression*> e, TypeEnv types,
auto TypeChecker::TypeCheckExp(Nonnull<Expression*> e, TypeEnv types,
Copy link
Contributor

Choose a reason for hiding this comment

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

To recap for future reference, the key issue is that in some circumstances, TypeCheckExp will reuse the input AST node as part of the output. That means in order for the output to be mutable, the input needs to be mutable. I think it's an open question whether that's the right approach long-term, but I think for purposes of this PR, keeping it non-const makes sense.

@jonmeow jonmeow merged commit 904c6f7 into carbon-language:trunk Sep 27, 2021
@jonmeow jonmeow deleted the mutable-ast branch September 27, 2021 17:57
chandlerc pushed a commit that referenced this pull request Jun 28, 2022
chandlerc pushed a commit that referenced this pull request Jun 28, 2022
The code is pretty intertwined: having the AST be truly mutable means (to me) changing parser.ypp to return non-const values, but then the way things are passed around between objects should be non-const (particularly an issue with lists), which then creates issues with construction of lists in the TypeChecker, which then TypeChecker needs to mostly be non-const.

Due to the difficulties in breaking this apart, whereas I'd previously considering refactoring accessor naming in the same PR, I've largely avoided doing so. The intent is then that this PR focuses mainly on const -> non-const AST behavior.

call_main moves out of interpreter.cpp so that interpreter.cpp can receive a fully const AST.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
cla: yes PR meets CLA requirements according to bot.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants