diff options
author | Philip Herron <philip.herron@embecosm.com> | 2020-11-30 22:59:20 +0000 |
---|---|---|
committer | Philip Herron <herron.philip@googlemail.com> | 2020-12-01 17:50:50 +0000 |
commit | 886b230d42e4a326e24f029e673ad1591159f7ad (patch) | |
tree | 323140e2d4794300b65c7a09eed2e63d35d36cbc /gcc/rust/analysis | |
parent | 37560f930d8068c1241fa1d5db9030b4287c3e66 (diff) | |
download | gcc-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
Diffstat (limited to 'gcc/rust/analysis')
-rw-r--r-- | gcc/rust/analysis/rust-type-resolution.cc | 164 |
1 files changed, 156 insertions, 8 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) {} |