mirror of
https://github.com/carbon-language/carbon-lang.git
synced 2026-10-05 11:51:04 +01:00
Add basic caller-side support for default values in check (#7800)
Modifies the arity check to include a lower-bound for arguments. Adds logic to pattern matching to supply default arguments for missing parameters.
This commit is contained in:
@@ -119,7 +119,9 @@ using State =
|
||||
class MatchContext {
|
||||
public:
|
||||
struct PreWork : Printable<PreWork> {
|
||||
// `None` when processing the callee side.
|
||||
// `None` when processing the callee side, or when processing the caller
|
||||
// side and no value was supplied, in expectation of using a default value
|
||||
// from the corresponding callee pattern.
|
||||
SemIR::InstId scrutinee_id;
|
||||
|
||||
auto Print(llvm::raw_ostream& out) const -> void {
|
||||
@@ -936,13 +938,31 @@ auto MatchContext::DoPreWork(State state,
|
||||
SemIR::DefaultValuePattern default_value_pattern,
|
||||
SemIR::InstId scrutinee_id, WorkItem entry)
|
||||
-> void {
|
||||
if (!std::holds_alternative<CalleeState*>(state)) {
|
||||
CARBON_FATAL("Unhandled state kind in DefaultValuePattern pre-work");
|
||||
CARBON_KIND_SWITCH(state) {
|
||||
case CARBON_KIND(CallerState* _): {
|
||||
// If there's no scrutinee supplied, supply the default value instead.
|
||||
if (!scrutinee_id.has_value()) {
|
||||
const auto& default_value = context_.default_values().Get(
|
||||
default_value_pattern.default_value_id);
|
||||
CARBON_CHECK(default_value.value_id.has_value());
|
||||
auto [inst_id, _] = WrapInstForSpecific(
|
||||
context_, SemIR::LocId(default_value.value_id),
|
||||
default_value.value_id, specific_id_stack_.back());
|
||||
scrutinee_id = inst_id;
|
||||
}
|
||||
break;
|
||||
}
|
||||
case CARBON_KIND(CalleeState* _): {
|
||||
// We will need to check the type of the parameter to make sure it
|
||||
// matches the provided default, so add ourselves to the post-work list.
|
||||
results_stack_.PushArray();
|
||||
AddAsPostWork(entry);
|
||||
break;
|
||||
}
|
||||
default: {
|
||||
CARBON_FATAL("Unhandled state kind in DefaultValuePattern pre-work");
|
||||
}
|
||||
}
|
||||
// We will need to check the type of the parameter to make sure it
|
||||
// matches the provided default, so add ourselves to the post-work list.
|
||||
results_stack_.PushArray();
|
||||
AddAsPostWork(entry);
|
||||
|
||||
// Process the subpattern for the default.
|
||||
AddWork({.pattern_id = default_value_pattern.subpattern_id,
|
||||
@@ -1226,9 +1246,19 @@ auto CallerPatternMatch(Context& context, SemIR::SpecificId specific_id,
|
||||
CARBON_CHECK(self_pattern_id.has_value());
|
||||
}
|
||||
|
||||
for (const auto& [arg_id, param_pattern_id] : llvm::zip_equal(
|
||||
// `arg_refs` may have a smaller arity than `param_patterns_id` due to the
|
||||
// possible presence of default values for some parameters. We use
|
||||
// `zip_longest` here to allow for that size disparity. But we presume we
|
||||
// always have a parameter pattern, so test that presumption here.
|
||||
CARBON_CHECK(self_arg_refs.size() + arg_refs.size() <=
|
||||
context.inst_blocks().GetOrEmpty(param_patterns_id).size());
|
||||
for (const auto& [maybe_arg_id, maybe_param_pattern_id] : llvm::zip_longest(
|
||||
llvm::concat<const SemIR::InstId>(self_arg_refs, arg_refs),
|
||||
context.inst_blocks().GetOrEmpty(param_patterns_id))) {
|
||||
CARBON_CHECK(maybe_param_pattern_id.has_value());
|
||||
const auto& param_pattern_id = *maybe_param_pattern_id;
|
||||
const auto& arg_id =
|
||||
maybe_arg_id.has_value() ? *maybe_arg_id : SemIR::InstId::None;
|
||||
match.Match(&state,
|
||||
{.pattern_id = param_pattern_id,
|
||||
.work = MatchContext::PreWork{.scrutinee_id = arg_id},
|
||||
|
||||
Reference in New Issue
Block a user