|
|
@@ -4,10 +4,13 @@
|
|
|
|
|
|
#include "explorer/interpreter/pattern_match.h"
|
|
|
|
|
|
+#include <algorithm>
|
|
|
+
|
|
|
#include "explorer/ast/value.h"
|
|
|
#include "explorer/base/arena.h"
|
|
|
#include "explorer/base/trace_stream.h"
|
|
|
#include "explorer/interpreter/action.h"
|
|
|
+#include "explorer/interpreter/type_utils.h"
|
|
|
#include "llvm/Support/Casting.h"
|
|
|
|
|
|
using llvm::cast;
|
|
|
@@ -202,14 +205,41 @@ auto PatternMatch(Nonnull<const Value*> p, ExpressionResult v,
|
|
|
// on the typechecker to ensure that `v.value()` is a type.
|
|
|
return true;
|
|
|
case Value::Kind::StaticArrayType: {
|
|
|
+ const auto& p_arr = cast<StaticArrayType>(*p);
|
|
|
switch (v.value()->kind()) {
|
|
|
case Value::Kind::TupleType:
|
|
|
case Value::Kind::TupleValue: {
|
|
|
- return true;
|
|
|
+ const auto& v_tup = cast<TupleValueBase>(*v.value());
|
|
|
+ if (v_tup.elements().empty()) {
|
|
|
+ return !TypeIsDeduceable(&p_arr.element_type());
|
|
|
+ }
|
|
|
+
|
|
|
+ std::vector<Nonnull<const Value*>> deduced_types;
|
|
|
+ deduced_types.reserve(v_tup.elements().size());
|
|
|
+ for (const auto& tup_elem : v_tup.elements()) {
|
|
|
+ if (!PatternMatch(&p_arr.element_type(), make_expr_result(tup_elem),
|
|
|
+ source_loc, bindings, generic_args, trace_stream,
|
|
|
+ arena)) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+
|
|
|
+ deduced_types.emplace_back(
|
|
|
+ DeducePatternType(&p_arr.element_type(), tup_elem, arena));
|
|
|
+ } // for
|
|
|
+
|
|
|
+ return std::adjacent_find(deduced_types.begin(), deduced_types.end(),
|
|
|
+ [](const auto& lhs, const auto& rhs) {
|
|
|
+ return !TypeEqual(lhs, rhs, std::nullopt);
|
|
|
+ }) == deduced_types.end();
|
|
|
}
|
|
|
case Value::Kind::StaticArrayType: {
|
|
|
const auto& v_arr = cast<StaticArrayType>(*v.value());
|
|
|
- return v_arr.has_size();
|
|
|
+ if (!v_arr.has_size()) {
|
|
|
+ return false;
|
|
|
+ }
|
|
|
+ return PatternMatch(
|
|
|
+ &p_arr.element_type(), make_expr_result(&v_arr.element_type()),
|
|
|
+ source_loc, bindings, generic_args, trace_stream, arena);
|
|
|
}
|
|
|
default:
|
|
|
return false;
|