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

Model var as a pattern operator #4720

Open
wants to merge 1 commit into
base: trunk
Choose a base branch
from

Conversation

geoffromer
Copy link
Contributor

No description provided.

Copy link
Contributor

@zygoloid zygoloid left a comment

Choose a reason for hiding this comment

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

I've only done some point checks on the test outputs so far, but this looks promising!

@@ -390,6 +390,13 @@ auto Context::LookupUnqualifiedName(Parse::NodeId node_id,
}

if (lexical_result.is_valid()) {
if (!full_pattern_stack_.IsBindNameUsable(lexical_result)) {
CARBON_DIAGNOSTIC(ReadDuringInitialization, Error,
"`{0}` read before initialization.", SemIR::NameId);
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
"`{0}` read before initialization.", SemIR::NameId);
"`{0}` read before initialization", SemIR::NameId);

Comment on lines +42 to +45
// 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;
Copy link
Contributor

Choose a reason for hiding this comment

The 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 ModifierOrder::Decl without adding extra state. Does that not work here?

// 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());
Copy link
Contributor

Choose a reason for hiding this comment

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

(Here and in EndPatternInitializer) Please avoid side-effects in CHECK macros.


// Returns false if the pattern that introduced `bind_inst_id` is currently
// being initialized.
auto IsBindNameUsable(SemIR::InstId bind_inst_id) const -> bool {
Copy link
Contributor

Choose a reason for hiding this comment

The 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 InstId in the lookup table, and replace it with the actual bind name instruction in PopFullPattern?

cast_type_id, type_node,
[&] {
CARBON_DIAGNOSTIC(IncompleteTypeInFieldDecl, Error,
"Field has incomplete type `{0}`.", SemIR::TypeId);
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
"Field has incomplete type `{0}`.", SemIR::TypeId);
"field has incomplete type `{0}`", SemIR::TypeId);

Comment on lines +230 to +231
if (auto interface_scope = context.GetCurrentScopeAs<SemIR::InterfaceDecl>();
interface_scope) {
Copy link
Contributor

Choose a reason for hiding this comment

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

I think this is long enough to be worth factoring out into a HandleAssociatedConstantDecl function; I think that'd make the similarity between handling of let and var decls a bit clearer too.

@@ -20,9 +20,7 @@ static auto GetCurrentFunction(Context& context) -> SemIR::Function& {
return context.functions().Get(function_id);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Would it make sense to move this to check/function.cpp now that it's being used more widely? Oh, or, perhaps we should rename it to something like GetCurrentFunctionForReturn given that the new usage is only in returned handling, and what we really mean here is "get me the function that a return here would return from" not some other notion of current / enclosing function.

// CHECK:STDOUT: name_binding_decl {
// CHECK:STDOUT: %x.patt: %empty_tuple.type = binding_pattern x
// CHECK:STDOUT: %.loc12_3.1: %empty_tuple.type = var_pattern %x.patt
// CHECK:STDOUT: }
// CHECK:STDOUT: %x.var: ref %empty_tuple.type = var x
Copy link
Contributor

Choose a reason for hiding this comment

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

The order of the output IR here is a bit surprising: first we create the var, then we initialize it (perhaps in-place), and only then do we evaluate the type expression that's involved in computing the type of the var. We're getting away with this because we can directly reference the type constant without mentioning the computation that produced it, but we should probably reorder these eventually so the type computation is spliced in prior to the var storage instruction.

Comment on lines +19 to +21
// TODO: is there a cleaner way to give VarAfterPattern access to the `var`
// token?
state.token = *(context.position() - 1);
Copy link
Contributor

Choose a reason for hiding this comment

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

We could change the token used for the VarAs* states to be the var token rather than the first token after it. (It used to be the token after because that was the start of the bracketed subtree, but we don't use the token field for that any more.)

break;
}
break;
if (loc_id.node_id().is_valid()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

Maybe use early exit here to reduce indentation?

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.

2 participants