-
Notifications
You must be signed in to change notification settings - Fork 1.5k
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
Model var
as a pattern operator
#4720
base: trunk
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -38,6 +38,11 @@ struct DeclIntroducerState { | |
|
||
// If there's an `extern library` in use, the library name. | ||
SemIR::LibraryNameId extern_library = SemIR::LibraryNameId::Invalid; | ||
|
||
// The node corresponding to the `returned` keyword (if any). We track this | ||
// separately from the other modifiers because the parser ensures it cannot | ||
// coexist with them. | ||
Parse::NodeId returned_node_id = Parse::NodeId::Invalid; | ||
Comment on lines
+42
to
+45
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I didn't understand this comment: specifically, because this modifier cannot coexist with any other modifier, it seems like we could model it using |
||
}; | ||
|
||
// Stack of `DeclIntroducerState` values, representing all the declaration | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,70 @@ | ||
// Part of the Carbon Language project, under the Apache License v2.0 with LLVM | ||
// Exceptions. See /LICENSE for license information. | ||
// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception | ||
|
||
#ifndef CARBON_TOOLCHAIN_CHECK_FULL_PATTERN_STACK_H_ | ||
#define CARBON_TOOLCHAIN_CHECK_FULL_PATTERN_STACK_H_ | ||
|
||
#include "common/array_stack.h" | ||
#include "common/check.h" | ||
#include "common/set.h" | ||
#include "toolchain/sem_ir/ids.h" | ||
|
||
namespace Carbon::Check { | ||
|
||
// Stack of full-patterns currently being checked. When a pattern | ||
// is followed by an explicit initializer, name bindings should not be used | ||
// within that initializer, although they are usable before it (within the | ||
// pattern) and after it. This class keeps track of those state transitions. | ||
// It is structured as a stack to handle situations like a pattern that | ||
// contains an initializer, or a pattern in a lambda in an expression pattern. | ||
// | ||
// TODO: Unify this with Context::pattern_block_stack, or differentiate them | ||
// more clearly. | ||
class FullPatternStack { | ||
public: | ||
// Marks the possible start of a new full-pattern (i.e. a pattern which occurs | ||
// in a non-pattern context). | ||
auto PushFullPattern() -> void { bind_name_stack_.PushArray(); } | ||
|
||
// Marks the start of the initializer for the full-pattern at the top of the | ||
// stack. | ||
auto StartPatternInitializer() -> void { | ||
for (SemIR::InstId bind_name_id : bind_name_stack_.PeekArray()) { | ||
CARBON_CHECK(unusable_bind_names_.Insert(bind_name_id).is_inserted()); | ||
geoffromer marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
} | ||
|
||
// Marks the end of the initializer for the full-pattern at the top of the | ||
// stack. | ||
auto EndPatternInitializer() -> void { | ||
for (SemIR::InstId bind_name_id : bind_name_stack_.PeekArray()) { | ||
CARBON_CHECK(unusable_bind_names_.Erase(bind_name_id)); | ||
} | ||
} | ||
|
||
// Marks the end of checking for the full-pattern at the top of the stack. | ||
// This cannot be called while processing an initializer for the top | ||
// pattern. | ||
auto PopFullPattern() -> void { bind_name_stack_.PopArray(); } | ||
|
||
// Records that `bind_inst_id` was introduced by the full-pattern at the | ||
// top of the stack. | ||
auto AddBindName(SemIR::InstId bind_inst_id) -> void { | ||
bind_name_stack_.AppendToTop(bind_inst_id); | ||
} | ||
|
||
// Returns false if the pattern that introduced `bind_inst_id` is currently | ||
// being initialized. | ||
auto IsBindNameUsable(SemIR::InstId bind_inst_id) const -> bool { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It looks like we're calling this for every unqualified name lookup. That sounds quite expensive; I wonder if we can find another way to approach this. Perhaps we could somehow tag the result in the lexical lookup structure to make it unusable before the end of the pattern. Can we put some kind of tombstone |
||
return !unusable_bind_names_.Contains(bind_inst_id); | ||
} | ||
|
||
private: | ||
ArrayStack<SemIR::InstId> bind_name_stack_; | ||
Set<SemIR::InstId> unusable_bind_names_; | ||
}; | ||
|
||
} // namespace Carbon::Check | ||
|
||
#endif // CARBON_TOOLCHAIN_CHECK_FULL_PATTERN_STACK_H_ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.