Skip to content

Commit 886b230

Browse files
committed
Add Type resolution to Array expressions
This adds type inferencing and validation for arrays such as: let x: [i32, 5] = [1,2,3,4,5] ley y = [1,2,3]; It checks that each element is of a valid type and they line up correctly. There needs to be some refactoring of the type resolution to handle the array index expressions so this is a good save point for now. Addresses: gcc-mirror#27 gcc-mirror#55
1 parent 37560f9 commit 886b230

File tree

3 files changed

+180
-14
lines changed

3 files changed

+180
-14
lines changed

gcc/rust/analysis/rust-type-resolution.cc

Lines changed: 156 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,13 @@ TypeResolution::typesAreCompatible (AST::Type *lhs, AST::Type *rhs,
104104
}
105105

106106
AST::Type *val = NULL;
107-
return scope.LookupType (lhsTypeStr, &val);
107+
if (!scope.LookupType (lhsTypeStr, &val))
108+
{
109+
rust_error_at (locus, "Unknown type: %s", lhsTypeStr.c_str ());
110+
return false;
111+
}
112+
113+
return true;
108114
}
109115

110116
bool
@@ -395,19 +401,112 @@ TypeResolution::visit (AST::CompoundAssignmentExpr &expr)
395401
void
396402
TypeResolution::visit (AST::GroupedExpr &expr)
397403
{}
398-
// void TypeResolution::visit(ArrayElems& elems) {}
404+
399405
void
400406
TypeResolution::visit (AST::ArrayElemsValues &elems)
401-
{}
407+
{
408+
// we need to generate the AST::ArrayType for this array init_expression
409+
// we can get the size via get_num_values() but we need to ensure each element
410+
// are type compatible
411+
412+
bool failed = false;
413+
AST::Type *last_inferred_type = nullptr;
414+
elems.iterate ([&] (AST::Expr *expr) mutable -> bool {
415+
size_t before;
416+
before = typeBuffer.size ();
417+
expr->accept_vis (*this);
418+
if (typeBuffer.size () <= before)
419+
{
420+
rust_error_at (expr->get_locus_slow (),
421+
"unable to determine element type");
422+
return false;
423+
}
424+
425+
AST::Type *inferedType = typeBuffer.back ();
426+
typeBuffer.pop_back ();
427+
428+
if (last_inferred_type == nullptr)
429+
last_inferred_type = inferedType;
430+
else
431+
{
432+
if (!typesAreCompatible (last_inferred_type, inferedType,
433+
expr->get_locus_slow ()))
434+
{
435+
failed = true;
436+
return false;
437+
}
438+
}
439+
440+
return true;
441+
});
442+
443+
// nothing to do when its failed
444+
if (failed)
445+
return;
446+
447+
auto capacity
448+
= new AST::LiteralExpr (std::to_string (elems.get_num_values ()),
449+
AST::Literal::INT,
450+
Linemap::predeclared_location ());
451+
auto arrayType = new AST::ArrayType (last_inferred_type->clone_type (),
452+
std::unique_ptr<AST::Expr> (capacity),
453+
Linemap::predeclared_location ());
454+
typeBuffer.push_back (arrayType);
455+
}
456+
402457
void
403458
TypeResolution::visit (AST::ArrayElemsCopied &elems)
404-
{}
459+
{
460+
printf ("ArrayElemsCopied: %s\n", elems.as_string ().c_str ());
461+
}
462+
405463
void
406464
TypeResolution::visit (AST::ArrayExpr &expr)
407-
{}
465+
{
466+
auto elements = expr.get_internal_elements ();
467+
elements->accept_vis (*this);
468+
}
469+
408470
void
409471
TypeResolution::visit (AST::ArrayIndexExpr &expr)
410-
{}
472+
{
473+
printf ("ArrayIndexExpr: %s\n", expr.as_string ().c_str ());
474+
475+
auto before = typeBuffer.size ();
476+
expr.get_array_expr ()->accept_vis (*this);
477+
if (typeBuffer.size () <= before)
478+
{
479+
rust_error_at (expr.get_locus_slow (),
480+
"unable to determine type for array index expression");
481+
return;
482+
}
483+
AST::Type *array_expr_type = typeBuffer.back ();
484+
typeBuffer.pop_back ();
485+
486+
before = typeBuffer.size ();
487+
expr.get_index_expr ()->accept_vis (*this);
488+
if (typeBuffer.size () <= before)
489+
{
490+
rust_error_at (expr.get_index_expr ()->get_locus_slow (),
491+
"unable to determine type for index expression");
492+
return;
493+
}
494+
495+
AST::Type *array_index_type = typeBuffer.back ();
496+
typeBuffer.pop_back ();
497+
498+
printf ("Array expr type %s array index expr type: [%s]\n",
499+
array_expr_type->as_string ().c_str (),
500+
array_index_type->as_string ().c_str ());
501+
502+
// the the element type from the array_expr_type and it _must_ be an array
503+
// TODO
504+
505+
// check the index_type should be an i32 which should really be
506+
// more permissive
507+
// TODO
508+
}
509+
411510
void
412511
TypeResolution::visit (AST::TupleExpr &expr)
413512
{}
@@ -1015,7 +1114,7 @@ TypeResolution::visit (AST::LetStmt &stmt)
10151114
return;
10161115
}
10171116

1018-
AST::Type *inferedType = NULL;
1117+
AST::Type *inferedType = nullptr;
10191118
if (stmt.has_init_expr ())
10201119
{
10211120
auto before = typeBuffer.size ();
@@ -1048,6 +1147,51 @@ TypeResolution::visit (AST::LetStmt &stmt)
10481147
return;
10491148
}
10501149
}
1150+
else if (stmt.has_type ())
1151+
{
1152+
auto before = typeComparisonBuffer.size ();
1153+
stmt.type->accept_vis (*this);
1154+
if (typeComparisonBuffer.size () <= before)
1155+
{
1156+
rust_error_at (stmt.locus, "failed to understand type for lhs");
1157+
return;
1158+
}
1159+
auto typeString = typeComparisonBuffer.back ();
1160+
typeComparisonBuffer.pop_back ();
1161+
1162+
AST::Type *val = NULL;
1163+
if (!scope.LookupType (typeString, &val))
1164+
{
1165+
rust_error_at (stmt.locus, "LetStmt has unknown type: %s",
1166+
stmt.type->as_string ().c_str ());
1167+
return;
1168+
}
1169+
}
1170+
else if (inferedType != nullptr)
1171+
{
1172+
auto before = typeComparisonBuffer.size ();
1173+
inferedType->accept_vis (*this);
1174+
if (typeComparisonBuffer.size () <= before)
1175+
{
1176+
rust_error_at (stmt.locus, "failed to understand type for lhs");
1177+
return;
1178+
}
1179+
auto typeString = typeComparisonBuffer.back ();
1180+
typeComparisonBuffer.pop_back ();
1181+
1182+
AST::Type *val = NULL;
1183+
if (!scope.LookupType (typeString, &val))
1184+
{
1185+
rust_error_at (stmt.locus, "Inferred unknown type: %s",
1186+
inferedType->as_string ().c_str ());
1187+
return;
1188+
}
1189+
}
1190+
else
1191+
{
1192+
rust_fatal_error (stmt.locus, "Failed to determine any type for LetStmt");
1193+
return;
1194+
}
10511195

10521196
// ensure the decl has the type set for compilation later on
10531197
if (!stmt.has_type ())
@@ -1115,9 +1259,13 @@ TypeResolution::visit (AST::RawPointerType &type)
11151259
void
11161260
TypeResolution::visit (AST::ReferenceType &type)
11171261
{}
1262+
11181263
void
11191264
TypeResolution::visit (AST::ArrayType &type)
1120-
{}
1265+
{
1266+
typeComparisonBuffer.push_back (type.get_element_type ()->as_string ());
1267+
}
1268+
11211269
void
11221270
TypeResolution::visit (AST::SliceType &type)
11231271
{}

gcc/rust/ast/rust-expr.h

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -928,6 +928,17 @@ class ArrayElemsValues : public ArrayElems
928928

929929
void accept_vis (ASTVisitor &vis) override;
930930

931+
size_t get_num_values () const { return values.size (); }
932+
933+
void iterate (std::function<bool (Expr *)> cb)
934+
{
935+
for (auto it = values.begin (); it != values.end (); it++)
936+
{
937+
if (!cb ((*it).get ()))
938+
return;
939+
}
940+
}
941+
931942
protected:
932943
ArrayElemsValues *clone_array_elems_impl () const override
933944
{
@@ -1037,6 +1048,8 @@ class ArrayExpr : public ExprWithoutBlock
10371048

10381049
void accept_vis (ASTVisitor &vis) override;
10391050

1051+
ArrayElems *get_internal_elements () { return internal_elements.get (); };
1052+
10401053
protected:
10411054
/* Use covariance to implement clone function as returning this object rather
10421055
* than base */
@@ -1100,6 +1113,9 @@ class ArrayIndexExpr : public ExprWithoutBlock
11001113

11011114
void accept_vis (ASTVisitor &vis) override;
11021115

1116+
Expr *get_array_expr () { return array_expr.get (); }
1117+
Expr *get_index_expr () { return index_expr.get (); }
1118+
11031119
protected:
11041120
/* Use covariance to implement clone function as returning this object rather
11051121
* than base */

gcc/rust/ast/rust-type.h

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ class ImplTraitType : public Type
6060
{
6161
// TypeParamBounds type_param_bounds;
6262
// inlined form
63-
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
63+
std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds;
6464

6565
Location locus;
6666

@@ -74,7 +74,7 @@ class ImplTraitType : public Type
7474

7575
public:
7676
ImplTraitType (
77-
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
77+
std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
7878
Location locus)
7979
: type_param_bounds (std::move (type_param_bounds)), locus (locus)
8080
{}
@@ -115,7 +115,7 @@ class TraitObjectType : public Type
115115
{
116116
bool has_dyn;
117117
// TypeParamBounds type_param_bounds;
118-
std::vector<std::unique_ptr<TypeParamBound>>
118+
std::vector<std::unique_ptr<TypeParamBound> >
119119
type_param_bounds; // inlined form
120120

121121
Location locus;
@@ -130,7 +130,7 @@ class TraitObjectType : public Type
130130

131131
public:
132132
TraitObjectType (
133-
std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
133+
std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
134134
Location locus, bool is_dyn_dispatch = false)
135135
: has_dyn (is_dyn_dispatch),
136136
type_param_bounds (std::move (type_param_bounds)), locus (locus)
@@ -318,14 +318,14 @@ class TypePath; // definition moved to "rust-path.h"
318318
* specific order */
319319
class TupleType : public TypeNoBounds
320320
{
321-
std::vector<std::unique_ptr<Type>> elems;
321+
std::vector<std::unique_ptr<Type> > elems;
322322
Location locus;
323323

324324
public:
325325
// Returns whether the tuple type is the unit type, i.e. has no elements.
326326
bool is_unit_type () const { return elems.empty (); }
327327

328-
TupleType (std::vector<std::unique_ptr<Type>> elems, Location locus)
328+
TupleType (std::vector<std::unique_ptr<Type> > elems, Location locus)
329329
: elems (std::move (elems)), locus (locus)
330330
{}
331331

@@ -574,6 +574,8 @@ class ArrayType : public TypeNoBounds
574574

575575
void accept_vis (ASTVisitor &vis) override;
576576

577+
Type *get_element_type () { return elem_type.get (); }
578+
577579
protected:
578580
/* Use covariance to implement clone function as returning this object rather
579581
* than base */

0 commit comments

Comments
 (0)