diff --git a/explorer/ast/pattern.h b/explorer/ast/pattern.h index 4ceeb100bd3a..5f5cff4c3c35 100644 --- a/explorer/ast/pattern.h +++ b/explorer/ast/pattern.h @@ -71,7 +71,10 @@ class Pattern : public AstNode { // Sets the value of this pattern. Can only be called once, during // typechecking. - void set_value(Nonnull value) { value_ = value; } + void set_value(Nonnull value) { + CARBON_CHECK(!value_) << "set_value called more than once"; + value_ = value; + } // Returns whether the value has been set. Should only be called // during typechecking: before typechecking it's guaranteed to be false, diff --git a/explorer/interpreter/action.cpp b/explorer/interpreter/action.cpp index dc7f292dc6ba..bda16c35dad1 100644 --- a/explorer/interpreter/action.cpp +++ b/explorer/interpreter/action.cpp @@ -124,9 +124,6 @@ void Action::Print(llvm::raw_ostream& out) const { case Action::Kind::WitnessAction: out << *cast(*this).witness() << " "; break; - case Action::Kind::PatternAction: - out << cast(*this).pattern() << " "; - break; case Action::Kind::StatementAction: cast(*this).statement().PrintDepth(1, out); out << " "; diff --git a/explorer/interpreter/action.h b/explorer/interpreter/action.h index 8ce055a86cb6..87b09d28926b 100644 --- a/explorer/interpreter/action.h +++ b/explorer/interpreter/action.h @@ -96,7 +96,6 @@ class Action { LValAction, ExpressionAction, WitnessAction, - PatternAction, StatementAction, DeclarationAction, ScopeAction, @@ -220,24 +219,6 @@ class WitnessAction : public Action { Nonnull witness_; }; -// An Action which implements evaluation of a Pattern. The result is expressed -// as a Value. -class PatternAction : public Action { - public: - explicit PatternAction(Nonnull pattern) - : Action(Kind::PatternAction), pattern_(pattern) {} - - static auto classof(const Action* action) -> bool { - return action->kind() == Kind::PatternAction; - } - - // The Pattern this Action evaluates. - auto pattern() const -> const Pattern& { return *pattern_; } - - private: - Nonnull pattern_; -}; - // An Action which implements execution of a Statement. Does not produce a // result. class StatementAction : public Action { diff --git a/explorer/interpreter/action_stack.cpp b/explorer/interpreter/action_stack.cpp index d14ab09f73cf..06178d774543 100644 --- a/explorer/interpreter/action_stack.cpp +++ b/explorer/interpreter/action_stack.cpp @@ -144,7 +144,6 @@ static auto FinishActionKindFor(Action::Kind kind) -> FinishActionKind { case Action::Kind::ExpressionAction: case Action::Kind::WitnessAction: case Action::Kind::LValAction: - case Action::Kind::PatternAction: return FinishActionKind::Value; case Action::Kind::StatementAction: case Action::Kind::DeclarationAction: diff --git a/explorer/interpreter/interpreter.cpp b/explorer/interpreter/interpreter.cpp index 2119cf7108aa..11591b7ae1d2 100644 --- a/explorer/interpreter/interpreter.cpp +++ b/explorer/interpreter/interpreter.cpp @@ -81,8 +81,6 @@ class Interpreter { auto StepLvalue() -> ErrorOr; // State transitions for witnesses. auto StepWitness() -> ErrorOr; - // State transitions for patterns. - auto StepPattern() -> ErrorOr; // State transition for statements. auto StepStmt() -> ErrorOr; // State transition for declarations. @@ -1582,85 +1580,6 @@ auto Interpreter::StepWitness() -> ErrorOr { } } -auto Interpreter::StepPattern() -> ErrorOr { - Action& act = todo_.CurrentAction(); - const Pattern& pattern = cast(act).pattern(); - if (trace_stream_) { - **trace_stream_ << "--- step pattern " << pattern << " ." << act.pos() - << ". (" << pattern.source_loc() << ") --->\n"; - } - switch (pattern.kind()) { - case PatternKind::AutoPattern: { - CARBON_CHECK(act.pos() == 0); - return todo_.FinishAction(arena_->New()); - } - case PatternKind::BindingPattern: { - const auto& binding = cast(pattern); - if (binding.name() != AnonymousName) { - return todo_.FinishAction( - arena_->New(&binding)); - } else { - return todo_.FinishAction(arena_->New()); - } - } - case PatternKind::GenericBinding: { - const auto& binding = cast(pattern); - return todo_.FinishAction(arena_->New(&binding)); - } - case PatternKind::TuplePattern: { - const auto& tuple = cast(pattern); - if (act.pos() < static_cast(tuple.fields().size())) { - // { { vk :: (f1=v1,..., fk=[],fk+1=ek+1,...) :: C, E, F} :: S, - // H} - // -> { { ek+1 :: (f1=v1,..., fk=vk, fk+1=[],...) :: C, E, F} :: S, - // H} - return todo_.Spawn( - std::make_unique(tuple.fields()[act.pos()])); - } else { - return todo_.FinishAction(arena_->New(act.results())); - } - } - case PatternKind::AlternativePattern: { - const auto& alternative = cast(pattern); - if (act.pos() == 0) { - return todo_.Spawn( - std::make_unique(&alternative.choice_type())); - } else if (act.pos() == 1) { - return todo_.Spawn( - std::make_unique(&alternative.arguments())); - } else { - CARBON_CHECK(act.pos() == 2); - const auto& choice_type = cast(*act.results()[0]); - return todo_.FinishAction(arena_->New( - alternative.alternative_name(), choice_type.name(), - act.results()[1])); - } - } - case PatternKind::ExpressionPattern: - if (act.pos() == 0) { - return todo_.Spawn(std::make_unique( - &cast(pattern).expression())); - } else { - return todo_.FinishAction(act.results()[0]); - } - case PatternKind::VarPattern: - if (act.pos() == 0) { - return todo_.Spawn(std::make_unique( - &cast(pattern).pattern())); - } else { - return todo_.FinishAction(act.results()[0]); - } - case PatternKind::AddrPattern: - const auto& addr = cast(pattern); - if (act.pos() == 0) { - return todo_.Spawn(std::make_unique(&addr.binding())); - } else { - return todo_.FinishAction(arena_->New(act.results()[0])); - } - break; - } -} - auto Interpreter::StepStmt() -> ErrorOr { Action& act = todo_.CurrentAction(); const Statement& stmt = cast(act).statement(); @@ -1706,7 +1625,8 @@ auto Interpreter::StepStmt() -> ErrorOr { constexpr int TargetVarPosInResult = 0; constexpr int CurrentIndexPosInResult = 1; constexpr int EndIndexPosInResult = 2; - constexpr int LoopVarPosInResult = 3; + const auto* loop_var = &cast( + cast(stmt).variable_declaration().value()); if (act.pos() == 0) { return todo_.Spawn( std::make_unique(&cast(stmt).loop_target())); @@ -1715,23 +1635,13 @@ auto Interpreter::StepStmt() -> ErrorOr { const auto* source_array = cast(act.results()[TargetVarPosInResult]); + int start_index = 0; auto end_index = static_cast(source_array->elements().size()); if (end_index == 0) { return todo_.FinishAction(); } - act.AddResult(arena_->New(0)); + act.AddResult(arena_->New(start_index)); act.AddResult(arena_->New(end_index)); - return todo_.Spawn(std::make_unique( - &cast(stmt).variable_declaration())); - } - if (act.pos() == 2) { - const auto* loop_var = - cast(act.results()[LoopVarPosInResult]); - const auto* source_array = - cast(act.results()[TargetVarPosInResult]); - - auto start_index = - cast(act.results()[CurrentIndexPosInResult])->value(); todo_.Initialize(*(loop_var->value_node()), source_array->elements()[start_index]); act.ReplaceResult(CurrentIndexPosInResult, @@ -1739,7 +1649,7 @@ auto Interpreter::StepStmt() -> ErrorOr { return todo_.Spawn( std::make_unique(&cast(stmt).body())); } - if (act.pos() >= 3) { + if (act.pos() >= 2) { auto current_index = cast(act.results()[CurrentIndexPosInResult])->value(); auto end_index = @@ -1748,8 +1658,6 @@ auto Interpreter::StepStmt() -> ErrorOr { if (current_index < end_index) { const auto* source_array = cast(act.results()[TargetVarPosInResult]); - const auto* loop_var = cast( - act.results()[LoopVarPosInResult]); CARBON_ASSIGN_OR_RETURN( Nonnull assigned_array_element, @@ -2125,9 +2033,6 @@ auto Interpreter::Step() -> ErrorOr { case Action::Kind::WitnessAction: CARBON_RETURN_IF_ERROR(StepWitness()); break; - case Action::Kind::PatternAction: - CARBON_RETURN_IF_ERROR(StepPattern()); - break; case Action::Kind::StatementAction: CARBON_RETURN_IF_ERROR(StepStmt()); break; @@ -2195,13 +2100,4 @@ auto InterpExp(Nonnull e, Nonnull arena, return interpreter.result(); } -auto InterpPattern(Nonnull p, Nonnull arena, - std::optional> trace_stream) - -> ErrorOr> { - Interpreter interpreter(Phase::CompileTime, arena, trace_stream); - CARBON_RETURN_IF_ERROR( - interpreter.RunAllSteps(std::make_unique(p))); - return interpreter.result(); -} - } // namespace Carbon diff --git a/explorer/interpreter/interpreter.h b/explorer/interpreter/interpreter.h index beb714e4ac89..7b9775c58844 100644 --- a/explorer/interpreter/interpreter.h +++ b/explorer/interpreter/interpreter.h @@ -34,13 +34,6 @@ auto InterpExp(Nonnull e, Nonnull arena, std::optional> trace_stream) -> ErrorOr>; -// Interprets `p` at compile-time, allocating values on `arena` and -// printing traces if `trace` is true. The caller must ensure that all the -// code this evaluates has been typechecked. -auto InterpPattern(Nonnull p, Nonnull arena, - std::optional> trace_stream) - -> ErrorOr>; - // Attempts to match `v` against the pattern `p`, returning whether matching // is successful. If it is, populates **bindings with the variables bound by // the match; `bindings` should only be nullopt in contexts where `p` diff --git a/explorer/interpreter/type_checker.cpp b/explorer/interpreter/type_checker.cpp index c915caeb60cc..78c153fbf191 100644 --- a/explorer/interpreter/type_checker.cpp +++ b/explorer/interpreter/type_checker.cpp @@ -42,16 +42,6 @@ using llvm::isa; namespace Carbon { -static void SetValue(Nonnull pattern, Nonnull value) { - // TODO: find some way to CHECK that `value` is identical to pattern->value(), - // if it's already set. Unclear if `ValueEqual` is suitable, because it - // currently focuses more on "real" values, and disallows the pseudo-values - // like `BindingPlaceholderValue` that we get in pattern evaluation. - if (!pattern->has_value()) { - pattern->set_value(value); - } -} - auto TypeChecker::IsSameType(Nonnull type1, Nonnull type2, const ImplScope& /*impl_scope*/) const -> bool { @@ -3822,6 +3812,7 @@ auto TypeChecker::TypeCheckPattern( switch (p->kind()) { case PatternKind::AutoPattern: { p->set_static_type(arena_->New()); + p->set_value(arena_->New()); return Success(); } case PatternKind::BindingPattern: { @@ -3834,9 +3825,7 @@ auto TypeChecker::TypeCheckPattern( } CARBON_RETURN_IF_ERROR(TypeCheckPattern( &binding.type(), std::nullopt, impl_scope, enclosing_value_category)); - CARBON_ASSIGN_OR_RETURN( - Nonnull type, - InterpPattern(&binding.type(), arena_, trace_stream_)); + Nonnull type = &binding.type().value(); // Convert to a type. // TODO: Convert the pattern before interpreting it rather than doing // this as a separate step. @@ -3878,9 +3867,9 @@ auto TypeChecker::TypeCheckPattern( CARBON_CHECK(!IsPlaceholderType(type)) << "should be no way to write a placeholder type"; binding.set_static_type(type); - CARBON_ASSIGN_OR_RETURN(Nonnull binding_value, - InterpPattern(&binding, arena_, trace_stream_)); - SetValue(&binding, binding_value); + binding.set_value(binding.name() != AnonymousName + ? arena_->New(&binding) + : arena_->New()); if (!binding.has_value_category()) { binding.set_value_category(enclosing_value_category); @@ -3901,6 +3890,7 @@ auto TypeChecker::TypeCheckPattern( case PatternKind::TuplePattern: { auto& tuple = cast(*p); std::vector> field_types; + std::vector> field_patterns; if (expected && (*expected)->kind() != Value::Kind::TupleType) { return ProgramError(p->source_loc()) << "didn't expect a tuple"; } @@ -3921,11 +3911,10 @@ auto TypeChecker::TypeCheckPattern( << "\n"; } field_types.push_back(&field->static_type()); + field_patterns.push_back(&field->value()); } tuple.set_static_type(arena_->New(std::move(field_types))); - CARBON_ASSIGN_OR_RETURN(Nonnull tuple_value, - InterpPattern(&tuple, arena_, trace_stream_)); - SetValue(&tuple, tuple_value); + tuple.set_value(arena_->New(std::move(field_patterns))); return Success(); } case PatternKind::AlternativePattern: { @@ -3962,10 +3951,9 @@ auto TypeChecker::TypeCheckPattern( TypeCheckPattern(&alternative.arguments(), substituted_parameter_type, impl_scope, enclosing_value_category)); alternative.set_static_type(&choice_type); - CARBON_ASSIGN_OR_RETURN( - Nonnull alternative_value, - InterpPattern(&alternative, arena_, trace_stream_)); - SetValue(&alternative, alternative_value); + alternative.set_value(arena_->New( + alternative.alternative_name(), choice_type.name(), + &alternative.arguments().value())); return Success(); } case PatternKind::ExpressionPattern: { @@ -3973,8 +3961,8 @@ auto TypeChecker::TypeCheckPattern( CARBON_RETURN_IF_ERROR(TypeCheckExp(&expression, impl_scope)); p->set_static_type(&expression.static_type()); CARBON_ASSIGN_OR_RETURN(Nonnull expr_value, - InterpPattern(p, arena_, trace_stream_)); - SetValue(p, expr_value); + InterpExp(&expression, arena_, trace_stream_)); + p->set_value(expr_value); return Success(); } case PatternKind::VarPattern: { @@ -3984,13 +3972,10 @@ auto TypeChecker::TypeCheckPattern( impl_scope, var_pattern.value_category())); var_pattern.set_static_type(&var_pattern.pattern().static_type()); - CARBON_ASSIGN_OR_RETURN( - Nonnull pattern_value, - InterpPattern(&var_pattern, arena_, trace_stream_)); - SetValue(&var_pattern, pattern_value); + var_pattern.set_value(&var_pattern.pattern().value()); return Success(); } - case PatternKind::AddrPattern: + case PatternKind::AddrPattern: { std::optional> expected_ptr; auto& addr_pattern = cast(*p); if (expected) { @@ -4007,11 +3992,10 @@ auto TypeChecker::TypeCheckPattern( return ProgramError(addr_pattern.source_loc()) << "Type associated with addr must be a pointer type."; } - CARBON_ASSIGN_OR_RETURN( - Nonnull pattern_value, - InterpPattern(&addr_pattern, arena_, trace_stream_)); - SetValue(&addr_pattern, pattern_value); + addr_pattern.set_value( + arena_->New(&addr_pattern.binding().value())); return Success(); + } } } @@ -4023,7 +4007,7 @@ auto TypeChecker::TypeCheckGenericBinding(GenericBinding& binding, // its symbolic identity before we type-check and interpret the type. auto* symbolic_value = arena_->New(&binding); binding.set_symbolic_identity(symbolic_value); - SetValue(&binding, symbolic_value); + binding.set_value(symbolic_value); CARBON_ASSIGN_OR_RETURN(Nonnull type, TypeCheckTypeExp(&binding.type(), impl_scope));