Add nested array size deduction from tuple (#2909)

As a follow up to #2825 this pr implements size deduction for nested
arrays.
E.g. `var x: [[i32;];] = ((1,2), (3,4));`.

Also updated the pattern matching logic for arrays, now it also checks
element types of the tuple size being deduced from. As a result code
like `var x: [i32;] = ("foo", "bar");`(note, that it tries to init an
array of i32 with a tuple of strings) fails to compile with a pattern
match error instead of an implicit cast failed error.

Moved some common type-related logic used in type_checker.cpp and
interpreter.cpp to the separate file.
This commit is contained in:
kshokhin
2023-11-20 20:20:21 +00:00
committed by GitHub
parent f59a6cdbdd
commit b6d660b4d9
17 changed files with 234 additions and 14 deletions
+32 -2
View File
@@ -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;