mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-09-24 22:02:23 +01:00
When parsing a pattern, if we encounter something that isn't pattern syntax, try parsing as an expression instead. We only need one-token lookahead to distinguish pattern syntax from expression syntax. Track a precedence group through pattern parsing so that we can allow different kinds of expressions in a top-level pattern (such as the operand of `let`) and in a nested pattern (such as a subpattern of a tuple pattern or within grouping parens). For example, we do not allow `case if ...`, and for now I've chosen to also not allow logical or relational operators at the top level of a pattern, so `case 1 + 1` is OK, but `case 1 == 1` and `case true and false` require parentheses. This decision should be ratified or revisited by a design proposal. Very basic check support is also provided, only sufficient to form an `ExprPattern` instruction and nothing beyond that. For now, all pattern matching against an `ExprPattern` fails with a TODO error. To support that, I've switched from calling `BeginSubpattern` in the parent handler of a pattern and `EndSubpatternAs*` in the pattern handler itself to calling both functions in parent handlers, with `EndSubpattern` converting an expression into an expression pattern where needed. Depends on #6976. Assisted-by: Gemini via Google Antigravity
81 lines
3.7 KiB
C++
81 lines
3.7 KiB
C++
// 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_PATTERN_H_
|
|
#define CARBON_TOOLCHAIN_CHECK_PATTERN_H_
|
|
|
|
#include "toolchain/check/context.h"
|
|
#include "toolchain/sem_ir/ids.h"
|
|
|
|
namespace Carbon::Check {
|
|
|
|
// Marks the start of a region of insts in a pattern context that might contain
|
|
// an expression. Typically this is called when handling a parse node that can
|
|
// immediately precede a subpattern (such as `let` or a `,` in a pattern list).
|
|
// `End[Empty]Subpattern` should be called later by the consumer of the
|
|
// subpattern.
|
|
auto BeginSubpattern(Context& context) -> void;
|
|
|
|
// Consumes the expression in a region started by the most recent
|
|
// BeginSubpattern, and returns the ID of the region. The region will not yet
|
|
// have any control-flow edges into or out of it.
|
|
auto ConsumeSubpatternExpr(Context& context, SemIR::InstId result_id)
|
|
-> SemIR::ExprRegionId;
|
|
|
|
// Ends a region started by BeginSubpattern (in stack order), asserting that
|
|
// it either had no expression content or the expression has been consumed.
|
|
auto EndEmptySubpattern(Context& context) -> void;
|
|
|
|
// Ends a region started by BeginSubpattern (in stack order). If the top of the
|
|
// node stack is an expression, the subpattern region is consumed and converted
|
|
// to an expression pattern, which replaces the expression on the node stack.
|
|
// Otherwise, the top of the node stack should be a pattern, in which case this
|
|
// asserts that the subpattern region is either empty or has been consumed.
|
|
//
|
|
// The node stack is passed explicitly as a reminder that this function affects
|
|
// the node stack, unlike the other *Subpattern functions.
|
|
auto EndSubpattern(Context& context, NodeStack& node_stack) -> void;
|
|
|
|
// Information about a created binding pattern.
|
|
struct BindingPatternInfo {
|
|
SemIR::InstId pattern_id;
|
|
SemIR::InstId bind_id;
|
|
};
|
|
|
|
// The phase of a binding pattern.
|
|
enum class BindingPhase { Template, Symbolic, Runtime };
|
|
|
|
// Creates an entity name for a binding pattern with the given properties.
|
|
auto AddBindingEntityName(Context& context, SemIR::NameId name_id,
|
|
SemIR::ConstantId form_id, bool is_unused,
|
|
BindingPhase phase) -> SemIR::EntityNameId;
|
|
|
|
// Creates a binding pattern and the associated binding inst, and returns their
|
|
// IDs. `type_region_id` is the region representing the binding's type
|
|
// expression.
|
|
auto AddBindingPattern(Context& context, SemIR::LocId name_loc,
|
|
SemIR::ExprRegionId type_region_id,
|
|
SemIR::AnyBindingPattern pattern) -> BindingPatternInfo;
|
|
|
|
// Creates storage for `var` patterns nested within the given pattern at the
|
|
// current location in the output SemIR. For a `returned var`, this
|
|
// reuses the function's return slot when present.
|
|
auto AddPatternVarStorage(Context& context, SemIR::InstBlockId pattern_block_id,
|
|
bool is_returned_var) -> void;
|
|
|
|
// Adds a parameter pattern with the specified name and type information. The
|
|
// pattern emulates `x: T` or `ref x: T` depending on the value of
|
|
// `is_ref` (`var x: T` is not supported). This only sets up the parameter
|
|
// pattern, binding pattern and type; callers are expected to add the returned
|
|
// parameter pattern instruction to appropriate blocks. This is used when
|
|
// generating functions, rather than processing a user-authored declaration.
|
|
auto AddParamPattern(Context& context, SemIR::LocId loc_id,
|
|
SemIR::NameId name_id,
|
|
SemIR::ExprRegionId type_expr_region_id,
|
|
SemIR::TypeId type_id, bool is_ref) -> SemIR::InstId;
|
|
|
|
} // namespace Carbon::Check
|
|
|
|
#endif // CARBON_TOOLCHAIN_CHECK_PATTERN_H_
|