aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPhilip Herron <philip.herron@embecosm.com>2020-11-30 22:59:20 +0000
committerPhilip Herron <herron.philip@googlemail.com>2020-12-01 17:50:50 +0000
commit886b230d42e4a326e24f029e673ad1591159f7ad (patch)
tree323140e2d4794300b65c7a09eed2e63d35d36cbc
parent37560f930d8068c1241fa1d5db9030b4287c3e66 (diff)
downloadgcc-886b230d42e4a326e24f029e673ad1591159f7ad.zip
gcc-886b230d42e4a326e24f029e673ad1591159f7ad.tar.gz
gcc-886b230d42e4a326e24f029e673ad1591159f7ad.tar.bz2
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: #27 #55
-rw-r--r--gcc/rust/analysis/rust-type-resolution.cc164
-rw-r--r--gcc/rust/ast/rust-expr.h16
-rw-r--r--gcc/rust/ast/rust-type.h14
3 files changed, 180 insertions, 14 deletions
diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc
index 707e0e8..aa2ea18 100644
--- a/gcc/rust/analysis/rust-type-resolution.cc
+++ b/gcc/rust/analysis/rust-type-resolution.cc
@@ -104,7 +104,13 @@ TypeResolution::typesAreCompatible (AST::Type *lhs, AST::Type *rhs,
}
AST::Type *val = NULL;
- return scope.LookupType (lhsTypeStr, &val);
+ if (!scope.LookupType (lhsTypeStr, &val))
+ {
+ rust_error_at (locus, "Unknown type: %s", lhsTypeStr.c_str ());
+ return false;
+ }
+
+ return true;
}
bool
@@ -395,19 +401,112 @@ TypeResolution::visit (AST::CompoundAssignmentExpr &expr)
void
TypeResolution::visit (AST::GroupedExpr &expr)
{}
-// void TypeResolution::visit(ArrayElems& elems) {}
+
void
TypeResolution::visit (AST::ArrayElemsValues &elems)
-{}
+{
+ // we need to generate the AST::ArrayType for this array init_expression
+ // we can get the size via get_num_values() but we need to ensure each element
+ // are type compatible
+
+ bool failed = false;
+ AST::Type *last_inferred_type = nullptr;
+ elems.iterate ([&] (AST::Expr *expr) mutable -> bool {
+ size_t before;
+ before = typeBuffer.size ();
+ expr->accept_vis (*this);
+ if (typeBuffer.size () <= before)
+ {
+ rust_error_at (expr->get_locus_slow (),
+ "unable to determine element type");
+ return false;
+ }
+
+ AST::Type *inferedType = typeBuffer.back ();
+ typeBuffer.pop_back ();
+
+ if (last_inferred_type == nullptr)
+ last_inferred_type = inferedType;
+ else
+ {
+ if (!typesAreCompatible (last_inferred_type, inferedType,
+ expr->get_locus_slow ()))
+ {
+ failed = true;
+ return false;
+ }
+ }
+
+ return true;
+ });
+
+ // nothing to do when its failed
+ if (failed)
+ return;
+
+ auto capacity
+ = new AST::LiteralExpr (std::to_string (elems.get_num_values ()),
+ AST::Literal::INT,
+ Linemap::predeclared_location ());
+ auto arrayType = new AST::ArrayType (last_inferred_type->clone_type (),
+ std::unique_ptr<AST::Expr> (capacity),
+ Linemap::predeclared_location ());
+ typeBuffer.push_back (arrayType);
+}
+
void
TypeResolution::visit (AST::ArrayElemsCopied &elems)
-{}
+{
+ printf ("ArrayElemsCopied: %s\n", elems.as_string ().c_str ());
+}
+
void
TypeResolution::visit (AST::ArrayExpr &expr)
-{}
+{
+ auto elements = expr.get_internal_elements ();
+ elements->accept_vis (*this);
+}
+
void
TypeResolution::visit (AST::ArrayIndexExpr &expr)
-{}
+{
+ printf ("ArrayIndexExpr: %s\n", expr.as_string ().c_str ());
+
+ auto before = typeBuffer.size ();
+ expr.get_array_expr ()->accept_vis (*this);
+ if (typeBuffer.size () <= before)
+ {
+ rust_error_at (expr.get_locus_slow (),
+ "unable to determine type for array index expression");
+ return;
+ }
+ AST::Type *array_expr_type = typeBuffer.back ();
+ typeBuffer.pop_back ();
+
+ before = typeBuffer.size ();
+ expr.get_index_expr ()->accept_vis (*this);
+ if (typeBuffer.size () <= before)
+ {
+ rust_error_at (expr.get_index_expr ()->get_locus_slow (),
+ "unable to determine type for index expression");
+ return;
+ }
+
+ AST::Type *array_index_type = typeBuffer.back ();
+ typeBuffer.pop_back ();
+
+ printf ("Array expr type %s array index expr type: [%s]\n",
+ array_expr_type->as_string ().c_str (),
+ array_index_type->as_string ().c_str ());
+
+ // the the element type from the array_expr_type and it _must_ be an array
+ // TODO
+
+ // check the index_type should be an i32 which should really be
+ // more permissive
+ // TODO
+}
+
void
TypeResolution::visit (AST::TupleExpr &expr)
{}
@@ -1015,7 +1114,7 @@ TypeResolution::visit (AST::LetStmt &stmt)
return;
}
- AST::Type *inferedType = NULL;
+ AST::Type *inferedType = nullptr;
if (stmt.has_init_expr ())
{
auto before = typeBuffer.size ();
@@ -1048,6 +1147,51 @@ TypeResolution::visit (AST::LetStmt &stmt)
return;
}
}
+ else if (stmt.has_type ())
+ {
+ auto before = typeComparisonBuffer.size ();
+ stmt.type->accept_vis (*this);
+ if (typeComparisonBuffer.size () <= before)
+ {
+ rust_error_at (stmt.locus, "failed to understand type for lhs");
+ return;
+ }
+ auto typeString = typeComparisonBuffer.back ();
+ typeComparisonBuffer.pop_back ();
+
+ AST::Type *val = NULL;
+ if (!scope.LookupType (typeString, &val))
+ {
+ rust_error_at (stmt.locus, "LetStmt has unknown type: %s",
+ stmt.type->as_string ().c_str ());
+ return;
+ }
+ }
+ else if (inferedType != nullptr)
+ {
+ auto before = typeComparisonBuffer.size ();
+ inferedType->accept_vis (*this);
+ if (typeComparisonBuffer.size () <= before)
+ {
+ rust_error_at (stmt.locus, "failed to understand type for lhs");
+ return;
+ }
+ auto typeString = typeComparisonBuffer.back ();
+ typeComparisonBuffer.pop_back ();
+
+ AST::Type *val = NULL;
+ if (!scope.LookupType (typeString, &val))
+ {
+ rust_error_at (stmt.locus, "Inferred unknown type: %s",
+ inferedType->as_string ().c_str ());
+ return;
+ }
+ }
+ else
+ {
+ rust_fatal_error (stmt.locus, "Failed to determine any type for LetStmt");
+ return;
+ }
// ensure the decl has the type set for compilation later on
if (!stmt.has_type ())
@@ -1115,9 +1259,13 @@ TypeResolution::visit (AST::RawPointerType &type)
void
TypeResolution::visit (AST::ReferenceType &type)
{}
+
void
TypeResolution::visit (AST::ArrayType &type)
-{}
+{
+ typeComparisonBuffer.push_back (type.get_element_type ()->as_string ());
+}
+
void
TypeResolution::visit (AST::SliceType &type)
{}
diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h
index fd6913f..d3e7cbd 100644
--- a/gcc/rust/ast/rust-expr.h
+++ b/gcc/rust/ast/rust-expr.h
@@ -928,6 +928,17 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ size_t get_num_values () const { return values.size (); }
+
+ void iterate (std::function<bool (Expr *)> cb)
+ {
+ for (auto it = values.begin (); it != values.end (); it++)
+ {
+ if (!cb ((*it).get ()))
+ return;
+ }
+ }
+
protected:
ArrayElemsValues *clone_array_elems_impl () const override
{
@@ -1037,6 +1048,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ ArrayElems *get_internal_elements () { return internal_elements.get (); };
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
@@ -1100,6 +1113,9 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Expr *get_array_expr () { return array_expr.get (); }
+ Expr *get_index_expr () { return index_expr.get (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */
diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h
index b396a44..301b664 100644
--- a/gcc/rust/ast/rust-type.h
+++ b/gcc/rust/ast/rust-type.h
@@ -60,7 +60,7 @@ class ImplTraitType : public Type
{
// TypeParamBounds type_param_bounds;
// inlined form
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds;
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds;
Location locus;
@@ -74,7 +74,7 @@ protected:
public:
ImplTraitType (
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
Location locus)
: type_param_bounds (std::move (type_param_bounds)), locus (locus)
{}
@@ -115,7 +115,7 @@ class TraitObjectType : public Type
{
bool has_dyn;
// TypeParamBounds type_param_bounds;
- std::vector<std::unique_ptr<TypeParamBound>>
+ std::vector<std::unique_ptr<TypeParamBound> >
type_param_bounds; // inlined form
Location locus;
@@ -130,7 +130,7 @@ protected:
public:
TraitObjectType (
- std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds,
+ std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds,
Location locus, bool is_dyn_dispatch = false)
: has_dyn (is_dyn_dispatch),
type_param_bounds (std::move (type_param_bounds)), locus (locus)
@@ -318,14 +318,14 @@ class TypePath; // definition moved to "rust-path.h"
* specific order */
class TupleType : public TypeNoBounds
{
- std::vector<std::unique_ptr<Type>> elems;
+ std::vector<std::unique_ptr<Type> > elems;
Location locus;
public:
// Returns whether the tuple type is the unit type, i.e. has no elements.
bool is_unit_type () const { return elems.empty (); }
- TupleType (std::vector<std::unique_ptr<Type>> elems, Location locus)
+ TupleType (std::vector<std::unique_ptr<Type> > elems, Location locus)
: elems (std::move (elems)), locus (locus)
{}
@@ -574,6 +574,8 @@ public:
void accept_vis (ASTVisitor &vis) override;
+ Type *get_element_type () { return elem_type.get (); }
+
protected:
/* Use covariance to implement clone function as returning this object rather
* than base */