From 0b9e73ab07a06d3dfc7b5bd63489626156299aea Mon Sep 17 00:00:00 2001 From: josh11b Date: Mon, 8 Jan 2024 18:46:10 -0800 Subject: [PATCH] Put check stage handle functions in execution order (#3573) No changes other than moving code and adding section comments. --- toolchain/check/handle_binding_pattern.cpp | 42 +++---- toolchain/check/handle_call_expr.cpp | 28 ++--- toolchain/check/handle_function.cpp | 94 +++++++------- toolchain/check/handle_let.cpp | 26 ++-- toolchain/check/handle_loop_statement.cpp | 138 +++++++++++---------- toolchain/check/handle_paren.cpp | 14 +-- toolchain/check/handle_pattern_list.cpp | 44 +++---- toolchain/check/handle_struct.cpp | 48 +++---- 8 files changed, 223 insertions(+), 211 deletions(-) diff --git a/toolchain/check/handle_binding_pattern.cpp b/toolchain/check/handle_binding_pattern.cpp index df78d1257c62..694df1a75335 100644 --- a/toolchain/check/handle_binding_pattern.cpp +++ b/toolchain/check/handle_binding_pattern.cpp @@ -9,27 +9,6 @@ namespace Carbon::Check { -auto HandleAddress(Context& context, Parse::AddressId parse_node) -> bool { - auto self_param_id = context.node_stack().PopPattern(); - if (auto self_param = - context.insts().TryGetAs(self_param_id); - self_param && - context.bind_names().Get(self_param->bind_name_id).name_id == - SemIR::NameId::SelfValue) { - // TODO: The type of an `addr_pattern` should probably be the non-pointer - // type, because that's the type that the pattern matches. - context.AddInstAndPush( - parse_node, - SemIR::AddrPattern{parse_node, self_param->type_id, self_param_id}); - } else { - CARBON_DIAGNOSTIC(AddrOnNonSelfParam, Error, - "`addr` can only be applied to a `self` parameter."); - context.emitter().Emit(TokenOnly(parse_node), AddrOnNonSelfParam); - context.node_stack().Push(parse_node, self_param_id); - } - return true; -} - auto HandleAnyBindingPattern(Context& context, Parse::NodeId parse_node, bool is_generic) -> bool { auto [type_node, parsed_type_id] = @@ -186,6 +165,27 @@ auto HandleGenericBindingPattern(Context& context, return HandleAnyBindingPattern(context, parse_node, /*is_generic=*/true); } +auto HandleAddress(Context& context, Parse::AddressId parse_node) -> bool { + auto self_param_id = context.node_stack().PopPattern(); + if (auto self_param = + context.insts().TryGetAs(self_param_id); + self_param && + context.bind_names().Get(self_param->bind_name_id).name_id == + SemIR::NameId::SelfValue) { + // TODO: The type of an `addr_pattern` should probably be the non-pointer + // type, because that's the type that the pattern matches. + context.AddInstAndPush( + parse_node, + SemIR::AddrPattern{parse_node, self_param->type_id, self_param_id}); + } else { + CARBON_DIAGNOSTIC(AddrOnNonSelfParam, Error, + "`addr` can only be applied to a `self` parameter."); + context.emitter().Emit(TokenOnly(parse_node), AddrOnNonSelfParam); + context.node_stack().Push(parse_node, self_param_id); + } + return true; +} + auto HandleTemplate(Context& context, Parse::TemplateId parse_node) -> bool { return context.TODO(parse_node, "HandleTemplate"); } diff --git a/toolchain/check/handle_call_expr.cpp b/toolchain/check/handle_call_expr.cpp index bbed176698e3..81a512773e7d 100644 --- a/toolchain/check/handle_call_expr.cpp +++ b/toolchain/check/handle_call_expr.cpp @@ -9,6 +9,20 @@ namespace Carbon::Check { +auto HandleCallExprStart(Context& context, Parse::CallExprStartId parse_node) + -> bool { + auto name_id = context.node_stack().PopExpr(); + context.node_stack().Push(parse_node, name_id); + context.ParamOrArgStart(); + return true; +} + +auto HandleCallExprComma(Context& context, + Parse::CallExprCommaId /*parse_node*/) -> bool { + context.ParamOrArgComma(); + return true; +} + auto HandleCallExpr(Context& context, Parse::CallExprId parse_node) -> bool { // Process the final explicit call argument now, but leave the arguments // block on the stack until the end of this function. @@ -83,18 +97,4 @@ auto HandleCallExpr(Context& context, Parse::CallExprId parse_node) -> bool { return true; } -auto HandleCallExprComma(Context& context, - Parse::CallExprCommaId /*parse_node*/) -> bool { - context.ParamOrArgComma(); - return true; -} - -auto HandleCallExprStart(Context& context, Parse::CallExprStartId parse_node) - -> bool { - auto name_id = context.node_stack().PopExpr(); - context.node_stack().Push(parse_node, name_id); - context.ParamOrArgStart(); - return true; -} - } // namespace Carbon::Check diff --git a/toolchain/check/handle_function.cpp b/toolchain/check/handle_function.cpp index 68da8eeb9bd5..26c29b3f4434 100644 --- a/toolchain/check/handle_function.cpp +++ b/toolchain/check/handle_function.cpp @@ -10,6 +10,32 @@ namespace Carbon::Check { +auto HandleFunctionIntroducer(Context& context, + Parse::FunctionIntroducerId parse_node) -> bool { + // Create an instruction block to hold the instructions created as part of the + // function signature, such as parameter and return types. + context.inst_block_stack().Push(); + // Push the bracketing node. + context.node_stack().Push(parse_node); + // Optional modifiers and the name follow. + context.decl_state_stack().Push(DeclState::Fn); + context.decl_name_stack().PushScopeAndStartName(); + return true; +} + +auto HandleReturnType(Context& context, Parse::ReturnTypeId parse_node) + -> bool { + // Propagate the type expression. + auto [type_parse_node, type_inst_id] = + context.node_stack().PopExprWithParseNode(); + auto type_id = ExprAsType(context, type_parse_node, type_inst_id); + // TODO: Use a dedicated instruction rather than VarStorage here. + context.AddInstAndPush( + parse_node, + SemIR::VarStorage{parse_node, type_id, SemIR::NameId::ReturnSlot}); + return true; +} + static auto DiagnoseModifiers(Context& context) -> KeywordModifierSet { Lex::TokenKind decl_kind = Lex::TokenKind::Fn; CheckAccessModifiersOnDecl(context, decl_kind); @@ -182,31 +208,6 @@ auto HandleFunctionDecl(Context& context, Parse::FunctionDeclId parse_node) return true; } -auto HandleFunctionDefinition(Context& context, - Parse::FunctionDefinitionId parse_node) -> bool { - SemIR::FunctionId function_id = - context.node_stack().Pop(); - - // If the `}` of the function is reachable, reject if we need a return value - // and otherwise add an implicit `return;`. - if (context.is_current_position_reachable()) { - if (context.functions().Get(function_id).return_type_id.is_valid()) { - CARBON_DIAGNOSTIC( - MissingReturnStatement, Error, - "Missing `return` at end of function with declared return type."); - context.emitter().Emit(TokenOnly(parse_node), MissingReturnStatement); - } else { - context.AddInst(SemIR::Return{parse_node}); - } - } - - context.PopScope(); - context.inst_block_stack().Pop(); - context.return_scope_stack().pop_back(); - context.decl_name_stack().PopScope(); - return true; -} - auto HandleFunctionDefinitionStart(Context& context, Parse::FunctionDefinitionStartId parse_node) -> bool { @@ -275,29 +276,28 @@ auto HandleFunctionDefinitionStart(Context& context, return true; } -auto HandleFunctionIntroducer(Context& context, - Parse::FunctionIntroducerId parse_node) -> bool { - // Create an instruction block to hold the instructions created as part of the - // function signature, such as parameter and return types. - context.inst_block_stack().Push(); - // Push the bracketing node. - context.node_stack().Push(parse_node); - // Optional modifiers and the name follow. - context.decl_state_stack().Push(DeclState::Fn); - context.decl_name_stack().PushScopeAndStartName(); - return true; -} +auto HandleFunctionDefinition(Context& context, + Parse::FunctionDefinitionId parse_node) -> bool { + SemIR::FunctionId function_id = + context.node_stack().Pop(); -auto HandleReturnType(Context& context, Parse::ReturnTypeId parse_node) - -> bool { - // Propagate the type expression. - auto [type_parse_node, type_inst_id] = - context.node_stack().PopExprWithParseNode(); - auto type_id = ExprAsType(context, type_parse_node, type_inst_id); - // TODO: Use a dedicated instruction rather than VarStorage here. - context.AddInstAndPush( - parse_node, - SemIR::VarStorage{parse_node, type_id, SemIR::NameId::ReturnSlot}); + // If the `}` of the function is reachable, reject if we need a return value + // and otherwise add an implicit `return;`. + if (context.is_current_position_reachable()) { + if (context.functions().Get(function_id).return_type_id.is_valid()) { + CARBON_DIAGNOSTIC( + MissingReturnStatement, Error, + "Missing `return` at end of function with declared return type."); + context.emitter().Emit(TokenOnly(parse_node), MissingReturnStatement); + } else { + context.AddInst(SemIR::Return{parse_node}); + } + } + + context.PopScope(); + context.inst_block_stack().Pop(); + context.return_scope_stack().pop_back(); + context.decl_name_stack().PopScope(); return true; } diff --git a/toolchain/check/handle_let.cpp b/toolchain/check/handle_let.cpp index 09839bd01a19..83928dcb3e03 100644 --- a/toolchain/check/handle_let.cpp +++ b/toolchain/check/handle_let.cpp @@ -9,6 +9,19 @@ namespace Carbon::Check { +auto HandleLetIntroducer(Context& context, Parse::LetIntroducerId parse_node) + -> bool { + context.decl_state_stack().Push(DeclState::Let); + // Push a bracketing node to establish the pattern context. + context.node_stack().Push(parse_node); + return true; +} + +auto HandleLetInitializer(Context& /*context*/, + Parse::LetInitializerId /*parse_node*/) -> bool { + return true; +} + auto HandleLetDecl(Context& context, Parse::LetDeclId parse_node) -> bool { auto value_id = context.node_stack().PopExpr(); if (context.node_stack().PeekIs()) { @@ -56,17 +69,4 @@ auto HandleLetDecl(Context& context, Parse::LetDeclId parse_node) -> bool { return true; } -auto HandleLetIntroducer(Context& context, Parse::LetIntroducerId parse_node) - -> bool { - context.decl_state_stack().Push(DeclState::Let); - // Push a bracketing node to establish the pattern context. - context.node_stack().Push(parse_node); - return true; -} - -auto HandleLetInitializer(Context& /*context*/, - Parse::LetInitializerId /*parse_node*/) -> bool { - return true; -} - } // namespace Carbon::Check diff --git a/toolchain/check/handle_loop_statement.cpp b/toolchain/check/handle_loop_statement.cpp index 5645354eeecf..f4a15086e1c0 100644 --- a/toolchain/check/handle_loop_statement.cpp +++ b/toolchain/check/handle_loop_statement.cpp @@ -7,69 +7,8 @@ namespace Carbon::Check { -auto HandleBreakStatement(Context& /*context*/, - Parse::BreakStatementId /*parse_node*/) -> bool { - return true; -} - -auto HandleBreakStatementStart(Context& context, - Parse::BreakStatementStartId parse_node) - -> bool { - auto& stack = context.break_continue_stack(); - if (stack.empty()) { - CARBON_DIAGNOSTIC(BreakOutsideLoop, Error, - "`break` can only be used in a loop."); - context.emitter().Emit(parse_node, BreakOutsideLoop); - } else { - context.AddInst(SemIR::Branch{parse_node, stack.back().break_target}); - } - - context.inst_block_stack().Pop(); - context.inst_block_stack().PushUnreachable(); - return true; -} - -auto HandleContinueStatement(Context& /*context*/, - Parse::ContinueStatementId /*parse_node*/) - -> bool { - return true; -} - -auto HandleContinueStatementStart(Context& context, - Parse::ContinueStatementStartId parse_node) - -> bool { - auto& stack = context.break_continue_stack(); - if (stack.empty()) { - CARBON_DIAGNOSTIC(ContinueOutsideLoop, Error, - "`continue` can only be used in a loop."); - context.emitter().Emit(parse_node, ContinueOutsideLoop); - } else { - context.AddInst(SemIR::Branch{parse_node, stack.back().continue_target}); - } - - context.inst_block_stack().Pop(); - context.inst_block_stack().PushUnreachable(); - return true; -} - -auto HandleForHeader(Context& context, Parse::ForHeaderId parse_node) -> bool { - return context.TODO(parse_node, "HandleForHeader"); -} - -auto HandleForHeaderStart(Context& context, Parse::ForHeaderStartId parse_node) - -> bool { - return context.TODO(parse_node, "HandleForHeaderStart"); -} - -auto HandleForIn(Context& context, Parse::ForInId parse_node) -> bool { - context.decl_state_stack().Pop(DeclState::Var); - return context.TODO(parse_node, "HandleForIn"); -} - -auto HandleForStatement(Context& context, Parse::ForStatementId parse_node) - -> bool { - return context.TODO(parse_node, "HandleForStatement"); -} +// `while` +// ------- auto HandleWhileConditionStart(Context& context, Parse::WhileConditionStartId parse_node) @@ -129,4 +68,77 @@ auto HandleWhileStatement(Context& context, Parse::WhileStatementId parse_node) return true; } +// `for` +// ----- + +auto HandleForHeaderStart(Context& context, Parse::ForHeaderStartId parse_node) + -> bool { + return context.TODO(parse_node, "HandleForHeaderStart"); +} + +auto HandleForIn(Context& context, Parse::ForInId parse_node) -> bool { + context.decl_state_stack().Pop(DeclState::Var); + return context.TODO(parse_node, "HandleForIn"); +} + +auto HandleForHeader(Context& context, Parse::ForHeaderId parse_node) -> bool { + return context.TODO(parse_node, "HandleForHeader"); +} + +auto HandleForStatement(Context& context, Parse::ForStatementId parse_node) + -> bool { + return context.TODO(parse_node, "HandleForStatement"); +} + +// `break` +// ------- + +auto HandleBreakStatementStart(Context& context, + Parse::BreakStatementStartId parse_node) + -> bool { + auto& stack = context.break_continue_stack(); + if (stack.empty()) { + CARBON_DIAGNOSTIC(BreakOutsideLoop, Error, + "`break` can only be used in a loop."); + context.emitter().Emit(parse_node, BreakOutsideLoop); + } else { + context.AddInst(SemIR::Branch{parse_node, stack.back().break_target}); + } + + context.inst_block_stack().Pop(); + context.inst_block_stack().PushUnreachable(); + return true; +} + +auto HandleBreakStatement(Context& /*context*/, + Parse::BreakStatementId /*parse_node*/) -> bool { + return true; +} + +// `continue` +// ---------- + +auto HandleContinueStatementStart(Context& context, + Parse::ContinueStatementStartId parse_node) + -> bool { + auto& stack = context.break_continue_stack(); + if (stack.empty()) { + CARBON_DIAGNOSTIC(ContinueOutsideLoop, Error, + "`continue` can only be used in a loop."); + context.emitter().Emit(parse_node, ContinueOutsideLoop); + } else { + context.AddInst(SemIR::Branch{parse_node, stack.back().continue_target}); + } + + context.inst_block_stack().Pop(); + context.inst_block_stack().PushUnreachable(); + return true; +} + +auto HandleContinueStatement(Context& /*context*/, + Parse::ContinueStatementId /*parse_node*/) + -> bool { + return true; +} + } // namespace Carbon::Check diff --git a/toolchain/check/handle_paren.cpp b/toolchain/check/handle_paren.cpp index d229a85491c8..a389eade0d16 100644 --- a/toolchain/check/handle_paren.cpp +++ b/toolchain/check/handle_paren.cpp @@ -6,6 +6,13 @@ namespace Carbon::Check { +auto HandleExprOpenParen(Context& context, Parse::ExprOpenParenId parse_node) + -> bool { + context.node_stack().Push(parse_node); + context.ParamOrArgStart(); + return true; +} + auto HandleParenExpr(Context& context, Parse::ParenExprId parse_node) -> bool { auto value_id = context.node_stack().PopExpr(); // ParamOrArgStart was called for tuple handling; clean up the ParamOrArg @@ -17,13 +24,6 @@ auto HandleParenExpr(Context& context, Parse::ParenExprId parse_node) -> bool { return true; } -auto HandleExprOpenParen(Context& context, Parse::ExprOpenParenId parse_node) - -> bool { - context.node_stack().Push(parse_node); - context.ParamOrArgStart(); - return true; -} - auto HandleTupleLiteralComma(Context& context, Parse::TupleLiteralCommaId /*parse_node*/) -> bool { diff --git a/toolchain/check/handle_pattern_list.cpp b/toolchain/check/handle_pattern_list.cpp index 97454852be33..a2e753687e5c 100644 --- a/toolchain/check/handle_pattern_list.cpp +++ b/toolchain/check/handle_pattern_list.cpp @@ -6,17 +6,6 @@ namespace Carbon::Check { -auto HandleImplicitParamList(Context& context, - Parse::ImplicitParamListId parse_node) -> bool { - auto refs_id = context.ParamOrArgEnd(Parse::NodeKind::ImplicitParamListStart); - context.node_stack() - .PopAndDiscardSoloParseNode(); - context.node_stack().Push(parse_node, refs_id); - // The implicit parameter list's scope extends to the end of the following - // parameter list. - return true; -} - auto HandleImplicitParamListStart(Context& context, Parse::ImplicitParamListStartId parse_node) -> bool { @@ -26,19 +15,14 @@ auto HandleImplicitParamListStart(Context& context, return true; } -auto HandleTuplePattern(Context& context, Parse::TuplePatternId parse_node) - -> bool { - auto refs_id = context.ParamOrArgEnd(Parse::NodeKind::TuplePatternStart); - context.PopScope(); +auto HandleImplicitParamList(Context& context, + Parse::ImplicitParamListId parse_node) -> bool { + auto refs_id = context.ParamOrArgEnd(Parse::NodeKind::ImplicitParamListStart); context.node_stack() - .PopAndDiscardSoloParseNode(); + .PopAndDiscardSoloParseNode(); context.node_stack().Push(parse_node, refs_id); - return true; -} - -auto HandlePatternListComma(Context& context, - Parse::PatternListCommaId /*parse_node*/) -> bool { - context.ParamOrArgComma(); + // The implicit parameter list's scope extends to the end of the following + // parameter list. return true; } @@ -61,4 +45,20 @@ auto HandleTuplePatternStart(Context& context, return true; } +auto HandlePatternListComma(Context& context, + Parse::PatternListCommaId /*parse_node*/) -> bool { + context.ParamOrArgComma(); + return true; +} + +auto HandleTuplePattern(Context& context, Parse::TuplePatternId parse_node) + -> bool { + auto refs_id = context.ParamOrArgEnd(Parse::NodeKind::TuplePatternStart); + context.PopScope(); + context.node_stack() + .PopAndDiscardSoloParseNode(); + context.node_stack().Push(parse_node, refs_id); + return true; +} + } // namespace Carbon::Check diff --git a/toolchain/check/handle_struct.cpp b/toolchain/check/handle_struct.cpp index 863dcbe8bd29..2d3a477a5016 100644 --- a/toolchain/check/handle_struct.cpp +++ b/toolchain/check/handle_struct.cpp @@ -7,9 +7,16 @@ namespace Carbon::Check { -auto HandleStructComma(Context& context, Parse::StructCommaId /*parse_node*/) +auto HandleStructLiteralOrStructTypeLiteralStart( + Context& context, Parse::StructLiteralOrStructTypeLiteralStartId parse_node) -> bool { - context.ParamOrArgComma(); + context.PushScope(); + context.node_stack().Push(parse_node); + // At this point we aren't sure whether this will be a value or type literal, + // so we push onto args irrespective. It just won't be used for a type + // literal. + context.args_type_info_stack().Push(); + context.ParamOrArgStart(); return true; } @@ -21,15 +28,9 @@ auto HandleStructFieldDesignator(Context& context, return true; } -auto HandleStructFieldType(Context& context, - Parse::StructFieldTypeId parse_node) -> bool { - auto [type_node, type_id] = context.node_stack().PopExprWithParseNode(); - SemIR::TypeId cast_type_id = ExprAsType(context, type_node, type_id); - - auto [name_node, name_id] = context.node_stack().PopNameWithParseNode(); - - context.AddInstAndPush( - parse_node, SemIR::StructTypeField{name_node, name_id, cast_type_id}); +auto HandleStructComma(Context& context, Parse::StructCommaId /*parse_node*/) + -> bool { + context.ParamOrArgComma(); return true; } @@ -47,6 +48,18 @@ auto HandleStructFieldValue(Context& context, return true; } +auto HandleStructFieldType(Context& context, + Parse::StructFieldTypeId parse_node) -> bool { + auto [type_node, type_id] = context.node_stack().PopExprWithParseNode(); + SemIR::TypeId cast_type_id = ExprAsType(context, type_node, type_id); + + auto [name_node, name_id] = context.node_stack().PopNameWithParseNode(); + + context.AddInstAndPush( + parse_node, SemIR::StructTypeField{name_node, name_id, cast_type_id}); + return true; +} + static auto DiagnoseDuplicateNames(Context& context, SemIR::InstBlockId type_block_id, llvm::StringRef construct) -> bool { @@ -98,19 +111,6 @@ auto HandleStructLiteral(Context& context, Parse::StructLiteralId parse_node) return true; } -auto HandleStructLiteralOrStructTypeLiteralStart( - Context& context, Parse::StructLiteralOrStructTypeLiteralStartId parse_node) - -> bool { - context.PushScope(); - context.node_stack().Push(parse_node); - // At this point we aren't sure whether this will be a value or type literal, - // so we push onto args irrespective. It just won't be used for a type - // literal. - context.args_type_info_stack().Push(); - context.ParamOrArgStart(); - return true; -} - auto HandleStructTypeLiteral(Context& context, Parse::StructTypeLiteralId parse_node) -> bool { auto refs_id = context.ParamOrArgEnd(