diff options
Diffstat (limited to 'gcc/rust/ast')
-rw-r--r-- | gcc/rust/ast/rust-ast-builder.cc | 226 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-builder.h | 122 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-collector.cc | 26 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast-visitor.cc | 8 | ||||
-rw-r--r-- | gcc/rust/ast/rust-ast.h | 27 | ||||
-rw-r--r-- | gcc/rust/ast/rust-collect-lang-items.cc | 9 | ||||
-rw-r--r-- | gcc/rust/ast/rust-collect-lang-items.h | 1 | ||||
-rw-r--r-- | gcc/rust/ast/rust-desugar-for-loops.cc | 204 | ||||
-rw-r--r-- | gcc/rust/ast/rust-desugar-for-loops.h | 108 | ||||
-rw-r--r-- | gcc/rust/ast/rust-desugar-question-mark.cc | 167 | ||||
-rw-r--r-- | gcc/rust/ast/rust-desugar-question-mark.h | 79 | ||||
-rw-r--r-- | gcc/rust/ast/rust-expr.h | 31 | ||||
-rw-r--r-- | gcc/rust/ast/rust-path.h | 4 | ||||
-rw-r--r-- | gcc/rust/ast/rust-pattern.cc | 1 | ||||
-rw-r--r-- | gcc/rust/ast/rust-stmt.h | 29 |
15 files changed, 984 insertions, 58 deletions
diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 47044df..cdc6eec 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -17,19 +17,31 @@ // <http://www.gnu.org/licenses/>. #include "rust-ast-builder.h" +#include "optional.h" #include "rust-ast-builder-type.h" #include "rust-ast.h" #include "rust-common.h" #include "rust-expr.h" +#include "rust-keyword-values.h" #include "rust-path.h" #include "rust-item.h" #include "rust-path.h" +#include "rust-pattern.h" #include "rust-system.h" #include "rust-token.h" +#include <memory> namespace Rust { namespace AST { +std::unique_ptr<Stmt> +Builder::statementify (std::unique_ptr<Expr> &&value, + bool semicolon_followed) const +{ + return std::make_unique<ExprStmt> (std::move (value), loc, + semicolon_followed); +} + std::unique_ptr<Expr> Builder::literal_string (std::string &&content) const { @@ -39,6 +51,17 @@ Builder::literal_string (std::string &&content) const } std::unique_ptr<Expr> +Builder::literal_bool (bool b) const +{ + auto str + = b ? Values::Keywords::TRUE_LITERAL : Values::Keywords::FALSE_LITERAL; + + return std::unique_ptr<Expr> ( + new AST::LiteralExpr (std::move (str), Literal::LitType::BOOL, + PrimitiveCoreType::CORETYPE_BOOL, {}, loc)); +} + +std::unique_ptr<Expr> Builder::call (std::unique_ptr<Expr> &&path, std::vector<std::unique_ptr<Expr>> &&args) const { @@ -64,6 +87,27 @@ Builder::array (std::vector<std::unique_ptr<Expr>> &&members) const } std::unique_ptr<Expr> +Builder::qualified_path_in_expression (std::unique_ptr<Type> &&type, + TypePath trait, + PathExprSegment segment) const +{ + auto segments = {segment}; + + return qualified_path_in_expression (std::move (type), trait, segments); +} + +std::unique_ptr<Expr> +Builder::qualified_path_in_expression ( + std::unique_ptr<Type> &&type, TypePath trait, + std::vector<PathExprSegment> &&segments) const +{ + auto qual_type = QualifiedPathType (std::move (type), loc, trait); + + return std::unique_ptr<QualifiedPathInExpression> ( + new QualifiedPathInExpression (qual_type, std::move (segments), {}, loc)); +} + +std::unique_ptr<Expr> Builder::identifier (std::string name) const { return std::unique_ptr<Expr> (new IdentifierExpr (name, {}, loc)); @@ -83,12 +127,48 @@ Builder::tuple_idx (std::string receiver, int idx) const new TupleIndexExpr (identifier (receiver), idx, {}, loc)); } +std::unique_ptr<Expr> +Builder::tuple (std::vector<std::unique_ptr<Expr>> &&values) const +{ + return std::unique_ptr<TupleExpr> ( + new TupleExpr (std::move (values), {}, {}, loc)); +} + +std::unique_ptr<Param> +Builder::self_ref_param (bool mutability) const +{ + return std::make_unique<SelfParam> (Lifetime::error (), mutability, loc); +} + +std::unique_ptr<Param> +Builder::function_param (std::unique_ptr<Pattern> &&pattern, + std::unique_ptr<Type> &&type) const +{ + return std::unique_ptr<FunctionParam> ( + new FunctionParam (std::move (pattern), std::move (type), {}, loc)); +} + FunctionQualifiers Builder::fn_qualifiers () const { return FunctionQualifiers (loc, Async::No, Const::No, Unsafety::Normal); } +std::unique_ptr<Function> +Builder::function (std::string function_name, + std::vector<std::unique_ptr<Param>> params, + std::unique_ptr<Type> return_type, + std::unique_ptr<BlockExpr> block, + std::vector<std::unique_ptr<GenericParam>> generic_params, + FunctionQualifiers qualifiers, WhereClause where_clause, + Visibility visibility) const +{ + return std::unique_ptr<Function> ( + new Function (function_name, qualifiers, std::move (generic_params), + std::move (params), std::move (return_type), where_clause, + std::move (block), visibility, {}, loc)); +} + PathExprSegment Builder::path_segment (std::string seg) const { @@ -159,12 +239,31 @@ Builder::single_generic_type_path (LangItem::Kind lang_item, } TypePath +Builder::type_path (std::vector<std::unique_ptr<TypePathSegment>> &&segments, + bool opening_scope) const +{ + return TypePath (std::move (segments), loc, opening_scope); +} + +TypePath +Builder::type_path (std::vector<std::string> &&segments, + bool opening_scope) const +{ + auto type_segments = std::vector<std::unique_ptr<TypePathSegment>> (); + + for (auto &&segment : segments) + type_segments.emplace_back (type_path_segment (segment)); + + return TypePath (std::move (type_segments), loc, opening_scope); +} + +TypePath Builder::type_path (std::unique_ptr<TypePathSegment> &&segment) const { auto segments = std::vector<std::unique_ptr<TypePathSegment>> (); segments.emplace_back (std::move (segment)); - return TypePath (std::move (segments), loc); + return type_path (std::move (segments)); } TypePath @@ -179,14 +278,23 @@ Builder::type_path (LangItem::Kind lang_item) const return type_path (type_path_segment (lang_item)); } +std::unique_ptr<Type> +Builder::reference_type (std::unique_ptr<TypeNoBounds> &&inner_type, + bool mutability) const +{ + return std::make_unique<ReferenceType> (mutability, std::move (inner_type), + loc); +} + PathInExpression -Builder::path_in_expression (std::vector<std::string> &&segments) const +Builder::path_in_expression (std::vector<std::string> &&segments, + bool opening_scope) const { auto path_segments = std::vector<PathExprSegment> (); for (auto &seg : segments) path_segments.emplace_back (path_segment (seg)); - return PathInExpression (std::move (path_segments), {}, loc); + return PathInExpression (std::move (path_segments), {}, loc, opening_scope); } PathInExpression @@ -195,32 +303,57 @@ Builder::path_in_expression (LangItem::Kind lang_item) const return PathInExpression (lang_item, {}, loc); } -std::unique_ptr<Expr> -Builder::block (std::unique_ptr<Stmt> &&stmt, +PathInExpression +Builder::variant_path (const std::string &enum_path, + const std::string &variant) const +{ + return PathInExpression ({path_segment (enum_path), path_segment (variant)}, + {}, loc, false); +} + +std::unique_ptr<BlockExpr> +Builder::block (tl::optional<std::unique_ptr<Stmt>> &&stmt, std::unique_ptr<Expr> &&tail_expr) const { auto stmts = std::vector<std::unique_ptr<Stmt>> (); - stmts.emplace_back (std::move (stmt)); + + if (stmt) + stmts.emplace_back (std::move (*stmt)); return block (std::move (stmts), std::move (tail_expr)); } -std::unique_ptr<Expr> +std::unique_ptr<BlockExpr> +Builder::block () const +{ + auto stmts = std::vector<std::unique_ptr<Stmt>> (); + + return block (std::move (stmts)); +} + +std::unique_ptr<BlockExpr> Builder::block (std::vector<std::unique_ptr<Stmt>> &&stmts, std::unique_ptr<Expr> &&tail_expr) const { - return std::unique_ptr<Expr> (new BlockExpr (std::move (stmts), - std::move (tail_expr), {}, {}, - LoopLabel::error (), loc, loc)); + return std::unique_ptr<BlockExpr> ( + new BlockExpr (std::move (stmts), std::move (tail_expr), {}, {}, + LoopLabel::error (), loc, loc)); +} + +std::unique_ptr<Expr> +Builder::return_expr (std::unique_ptr<Expr> &&to_return) +{ + return std::unique_ptr<Expr> ( + new ReturnExpr (std::move (to_return), {}, loc)); } std::unique_ptr<Stmt> -Builder::let (std::unique_ptr<Pattern> pattern, std::unique_ptr<Type> type, - std::unique_ptr<Expr> init) const +Builder::let (std::unique_ptr<Pattern> &&pattern, std::unique_ptr<Type> &&type, + std::unique_ptr<Expr> &&init) const { return std::unique_ptr<Stmt> (new LetStmt (std::move (pattern), std::move (init), std::move (type), - {}, loc)); + tl::nullopt, {}, loc)); } std::unique_ptr<Expr> @@ -238,6 +371,24 @@ Builder::deref (std::unique_ptr<Expr> &&of) const return std::unique_ptr<Expr> (new DereferenceExpr (std::move (of), {}, loc)); } +std::unique_ptr<Expr> +Builder::comparison_expr (std::unique_ptr<Expr> &&lhs, + std::unique_ptr<Expr> &&rhs, + ComparisonOperator op) const +{ + return std::make_unique<ComparisonExpr> (std::move (lhs), std::move (rhs), op, + loc); +} + +std::unique_ptr<Expr> +Builder::boolean_operation (std::unique_ptr<Expr> &&lhs, + std::unique_ptr<Expr> &&rhs, + LazyBooleanOperator op) const +{ + return std::make_unique<LazyBooleanExpr> (std::move (lhs), std::move (rhs), + op, loc); +} + std::unique_ptr<Stmt> Builder::struct_struct (std::string struct_name, std::vector<std::unique_ptr<GenericParam>> &&generics, @@ -297,6 +448,13 @@ Builder::wildcard () const return std::unique_ptr<Pattern> (new WildcardPattern (loc)); } +std::unique_ptr<Pattern> +Builder::ref_pattern (std::unique_ptr<Pattern> &&inner) const +{ + return std::make_unique<ReferencePattern> (std::move (inner), false, false, + loc); +} + std::unique_ptr<Path> Builder::lang_item_path (LangItem::Kind kind) const { @@ -330,11 +488,39 @@ Builder::match_case (std::unique_ptr<Pattern> &&pattern, std::unique_ptr<Expr> Builder::loop (std::vector<std::unique_ptr<Stmt>> &&stmts) { - auto block = std::unique_ptr<BlockExpr> ( - new BlockExpr (std::move (stmts), nullptr, {}, {}, LoopLabel::error (), loc, - loc)); + auto block_expr = block (std::move (stmts), nullptr); - return std::unique_ptr<Expr> (new LoopExpr (std::move (block), loc)); + return std::unique_ptr<Expr> (new LoopExpr (std::move (block_expr), loc)); +} + +std::unique_ptr<TypeParamBound> +Builder::trait_bound (TypePath bound) +{ + return std::make_unique<TraitBound> (bound, loc); +} + +std::unique_ptr<Item> +Builder::trait_impl (TypePath trait_path, std::unique_ptr<Type> target, + std::vector<std::unique_ptr<AssociatedItem>> trait_items, + std::vector<std::unique_ptr<GenericParam>> generics, + WhereClause where_clause, Visibility visibility) const +{ + return std::unique_ptr<Item> ( + new TraitImpl (trait_path, /* unsafe */ false, + /* exclam */ false, std::move (trait_items), + std::move (generics), std::move (target), where_clause, + visibility, {}, {}, loc)); +} + +std::unique_ptr<GenericParam> +Builder::generic_type_param ( + std::string type_representation, + std::vector<std::unique_ptr<TypeParamBound>> &&bounds, + std::unique_ptr<Type> &&type) +{ + return std::make_unique<TypeParam> (type_representation, loc, + std::move (bounds), std::move (type), + std::vector<Attribute> ()); } std::unique_ptr<Type> @@ -361,7 +547,8 @@ Builder::new_lifetime_param (LifetimeParam ¶m) } std::unique_ptr<GenericParam> -Builder::new_type_param (TypeParam ¶m) +Builder::new_type_param ( + TypeParam ¶m, std::vector<std::unique_ptr<TypeParamBound>> extra_bounds) { location_t locus = param.get_locus (); AST::AttrVec outer_attrs = param.get_outer_attrs (); @@ -372,6 +559,9 @@ Builder::new_type_param (TypeParam ¶m) if (param.has_type ()) type = new_type (param.get_type ()); + for (auto &&extra_bound : extra_bounds) + type_param_bounds.emplace_back (std::move (extra_bound)); + for (const auto &b : param.get_type_param_bounds ()) { switch (b->get_bound_type ()) diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index e5bae6e..41ce118 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -23,6 +23,7 @@ #include "rust-expr.h" #include "rust-ast.h" #include "rust-item.h" +#include "rust-operators.h" namespace Rust { namespace AST { @@ -50,6 +51,14 @@ vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2) return v; } +/* Pointer-ify something */ +template <typename T> +static std::unique_ptr<T> +ptrify (T value) +{ + return std::unique_ptr<T> (new T (value)); +} + // TODO: Use this builder when expanding regular macros /* Builder class with helper methods to create AST nodes. This builder is * tailored towards generating multiple AST nodes from a single location, and @@ -59,9 +68,16 @@ class Builder public: Builder (location_t loc) : loc (loc) {} + /* Create an expression statement from an expression */ + std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&value, + bool semicolon_followed = true) const; + /* Create a string literal expression ("content") */ std::unique_ptr<Expr> literal_string (std::string &&content) const; + /* Create a boolean literal expression (true) */ + std::unique_ptr<Expr> literal_bool (bool b) const; + /* Create an identifier expression (`variable`) */ std::unique_ptr<Expr> identifier (std::string name) const; std::unique_ptr<Pattern> identifier_pattern (std::string name, @@ -70,6 +86,10 @@ public: /* Create a tuple index expression (`receiver.0`) */ std::unique_ptr<Expr> tuple_idx (std::string receiver, int idx) const; + /* Create a tuple expression (`(a1, a2, a3)`) */ + std::unique_ptr<Expr> tuple (std::vector<std::unique_ptr<Expr>> &&values + = {}) const; + /* Create a reference to an expression (`&of`) */ std::unique_ptr<Expr> ref (std::unique_ptr<Expr> &&of, bool mut = false) const; @@ -77,26 +97,43 @@ public: /* Create a dereference of an expression (`*of`) */ std::unique_ptr<Expr> deref (std::unique_ptr<Expr> &&of) const; + /* Build a comparison expression (`lhs == rhs`) */ + std::unique_ptr<Expr> comparison_expr (std::unique_ptr<Expr> &&lhs, + std::unique_ptr<Expr> &&rhs, + ComparisonOperator op) const; + + /* Build a lazy boolean operator expression (`lhs && rhs`) */ + std::unique_ptr<Expr> boolean_operation (std::unique_ptr<Expr> &&lhs, + std::unique_ptr<Expr> &&rhs, + LazyBooleanOperator op) const; + /* Create a block with an optional tail expression */ - std::unique_ptr<Expr> block (std::vector<std::unique_ptr<Stmt>> &&stmts, - std::unique_ptr<Expr> &&tail_expr - = nullptr) const; - std::unique_ptr<Expr> block (std::unique_ptr<Stmt> &&stmt, - std::unique_ptr<Expr> &&tail_expr - = nullptr) const; + std::unique_ptr<BlockExpr> block (std::vector<std::unique_ptr<Stmt>> &&stmts, + std::unique_ptr<Expr> &&tail_expr + = nullptr) const; + std::unique_ptr<BlockExpr> block (tl::optional<std::unique_ptr<Stmt>> &&stmt, + std::unique_ptr<Expr> &&tail_expr + = nullptr) const; + /* Create an empty block */ + std::unique_ptr<BlockExpr> block () const; + + /* Create an early return expression with an optional expression */ + std::unique_ptr<Expr> return_expr (std::unique_ptr<Expr> &&to_return + = nullptr); /* Create a let binding with an optional type and initializer (`let <name> : * <type> = <init>`) */ - std::unique_ptr<Stmt> let (std::unique_ptr<Pattern> pattern, - std::unique_ptr<Type> type = nullptr, - std::unique_ptr<Expr> init = nullptr) const; + std::unique_ptr<Stmt> let (std::unique_ptr<Pattern> &&pattern, + std::unique_ptr<Type> &&type = nullptr, + std::unique_ptr<Expr> &&init = nullptr) const; /** * Create a call expression to a function, struct or enum variant, given its * arguments (`path(arg0, arg1, arg2)`) */ std::unique_ptr<Expr> call (std::unique_ptr<Expr> &&path, - std::vector<std::unique_ptr<Expr>> &&args) const; + std::vector<std::unique_ptr<Expr>> &&args + = {}) const; std::unique_ptr<Expr> call (std::unique_ptr<Expr> &&path, std::unique_ptr<Expr> &&arg) const; @@ -106,9 +143,35 @@ public: std::unique_ptr<Expr> array (std::vector<std::unique_ptr<Expr>> &&members) const; + /* Create a qualified path in expression (`<type as Trait>::seg::expr`) */ + std::unique_ptr<Expr> + qualified_path_in_expression (std::unique_ptr<Type> &&type, TypePath trait, + PathExprSegment segment) const; + std::unique_ptr<Expr> + qualified_path_in_expression (std::unique_ptr<Type> &&type, TypePath trait, + std::vector<PathExprSegment> &&segments + = {}) const; + + /* Self parameter for a function definition (`&self`) */ + std::unique_ptr<Param> self_ref_param (bool mutability = false) const; + /* A regular named function parameter for a definition (`a: type`) */ + std::unique_ptr<Param> function_param (std::unique_ptr<Pattern> &&pattern, + std::unique_ptr<Type> &&type) const; + /* Empty function qualifiers, with no specific qualifiers */ FunctionQualifiers fn_qualifiers () const; + std::unique_ptr<Function> + function (std::string function_name, + std::vector<std::unique_ptr<Param>> params, + std::unique_ptr<Type> return_type, std::unique_ptr<BlockExpr> block, + std::vector<std::unique_ptr<GenericParam>> generic_params = {}, + FunctionQualifiers qualifiers + = FunctionQualifiers (UNKNOWN_LOCATION, Async::No, Const::No, + Unsafety::Normal), + WhereClause where_clause = WhereClause::create_empty (), + Visibility visibility = Visibility::create_private ()) const; + /* Create a single path segment from one string */ PathExprSegment path_segment (std::string seg) const; @@ -132,23 +195,35 @@ public: std::unique_ptr<Type> single_generic_type_path (LangItem::Kind lang_item, GenericArgs args) const; + TypePath type_path (std::vector<std::unique_ptr<TypePathSegment>> &&segment, + bool opening_scope = false) const; + TypePath type_path (std::vector<std::string> &&segments, + bool opening_scope = false) const; TypePath type_path (std::unique_ptr<TypePathSegment> &&segment) const; TypePath type_path (std::string type) const; TypePath type_path (LangItem::Kind lang_item) const; + std::unique_ptr<Type> + reference_type (std::unique_ptr<TypeNoBounds> &&inner_type, + bool mutability = false) const; + /** * Create a path in expression from multiple segments (`Clone::clone`). You * do not need to separate the segments using `::`, you can simply provide a * vector of strings to the functions which will get turned into path segments */ - PathInExpression - path_in_expression (std::vector<std::string> &&segments) const; + PathInExpression path_in_expression (std::vector<std::string> &&segments, + bool opening_scope = false) const; /** * Create a path in expression from a lang item. */ PathInExpression path_in_expression (LangItem::Kind lang_item) const; + /* Create the path to an enum's variant (`Result::Ok`) */ + PathInExpression variant_path (const std::string &enum_path, + const std::string &variant) const; + /* Create a new struct */ std::unique_ptr<Stmt> struct_struct (std::string struct_name, @@ -160,8 +235,8 @@ public: /** * Create an expression for struct instantiation with fields (`S { a, b: c }`) - * Tuple expressions are call expressions and can thus be constructed with - * `call` + * Named tuple expressions (`S(a, b, c)`) are call expressions and can thus be + * constructed with `call` */ std::unique_ptr<Expr> struct_expr (std::string struct_name, @@ -181,6 +256,8 @@ public: /* Create a wildcard pattern (`_`) */ std::unique_ptr<Pattern> wildcard () const; + /* Create a reference pattern (`&pattern`) */ + std::unique_ptr<Pattern> ref_pattern (std::unique_ptr<Pattern> &&inner) const; /* Create a lang item path usable as a general path */ std::unique_ptr<Path> lang_item_path (LangItem::Kind) const; @@ -195,12 +272,27 @@ public: /* Create a loop expression */ std::unique_ptr<Expr> loop (std::vector<std::unique_ptr<Stmt>> &&stmts); + std::unique_ptr<TypeParamBound> trait_bound (TypePath bound); + std::unique_ptr<Item> + trait_impl (TypePath trait_path, std::unique_ptr<Type> target, + std::vector<std::unique_ptr<AssociatedItem>> trait_items = {}, + std::vector<std::unique_ptr<GenericParam>> generics = {}, + WhereClause where_clause = WhereClause::create_empty (), + Visibility visibility = Visibility::create_private ()) const; + + std::unique_ptr<GenericParam> + generic_type_param (std::string type_representation, + std::vector<std::unique_ptr<TypeParamBound>> &&bounds, + std::unique_ptr<Type> &&type = nullptr); + static std::unique_ptr<Type> new_type (Type &type); static std::unique_ptr<GenericParam> new_lifetime_param (LifetimeParam ¶m); - static std::unique_ptr<GenericParam> new_type_param (TypeParam ¶m); + static std::unique_ptr<GenericParam> new_type_param ( + TypeParam ¶m, + std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {}); static Lifetime new_lifetime (const Lifetime &lifetime); diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index 978de64..3297407 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -15,12 +15,15 @@ // You should have received a copy of the GNU General Public License // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. + #include "rust-ast-collector.h" #include "rust-ast.h" #include "rust-diagnostics.h" #include "rust-expr.h" #include "rust-item.h" #include "rust-keyword-values.h" +#include "rust-location.h" +#include "rust-path.h" #include "rust-system.h" #include "rust-token.h" @@ -530,11 +533,23 @@ TokenCollector::visit (PathExprSegment &segment) void TokenCollector::visit (PathInExpression &path) { - if (path.opening_scope_resolution ()) + if (path.is_lang_item ()) { - push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); + push (Rust::Token::make (TokenId::HASH, path.get_locus ())); + push (Rust::Token::make (TokenId::LEFT_SQUARE, path.get_locus ())); + push (Rust::Token::make_identifier (path.get_locus (), "lang")); + push (Rust::Token::make (TokenId::EQUAL, path.get_locus ())); + push ( + Rust::Token::make_string (path.get_locus (), + LangItem::ToString (path.get_lang_item ()))); + push (Rust::Token::make (TokenId::RIGHT_SQUARE, path.get_locus ())); + + return; } + if (path.opening_scope_resolution ()) + push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); + visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION); } @@ -2573,6 +2588,13 @@ TokenCollector::visit (LetStmt &stmt) push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); visit (stmt.get_init_expr ()); } + + if (stmt.has_else_expr ()) + { + push (Rust::Token::make (ELSE, UNDEF_LOCATION)); + visit (stmt.get_else_expr ()); + } + push (Rust::Token::make (SEMICOLON, UNDEF_LOCATION)); } diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index e2e2d9d..ba5f87b 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -89,8 +89,10 @@ void DefaultASTVisitor::visit (AST::PathInExpression &path) { visit_outer_attrs (path); - for (auto &segment : path.get_segments ()) - visit (segment); + + if (!path.is_lang_item ()) + for (auto &segment : path.get_segments ()) + visit (segment); } void @@ -390,6 +392,7 @@ DefaultASTVisitor::visit (AST::StructExprStructFields &expr) { visit_outer_attrs (expr); visit_inner_attrs (expr); + visit (expr.get_struct_name ()); if (expr.has_struct_base ()) visit (expr.get_struct_base ()); for (auto &field : expr.get_fields ()) @@ -401,6 +404,7 @@ DefaultASTVisitor::visit (AST::StructExprStructBase &expr) { visit_outer_attrs (expr); visit_inner_attrs (expr); + visit (expr.get_struct_name ()); visit (expr.get_struct_base ()); } diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 5e724d1..4d7d23d 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1263,6 +1263,16 @@ public: Identifier, FormatArgs, MacroInvocation, + Borrow, + Dereference, + ErrorPropagation, + Negation, + ArithmeticOrLogical, + Comparison, + LazyBoolean, + TypeCast, + Assignment, + CompoundAssignment, }; virtual Kind get_expr_kind () const = 0; @@ -1986,13 +1996,6 @@ public: return std::move (item); } - std::unique_ptr<AssociatedItem> take_trait_item () - { - rust_assert (!is_error ()); - return std::unique_ptr<AssociatedItem> ( - static_cast<AssociatedItem *> (assoc_item.release ())); - } - std::unique_ptr<ExternalItem> take_external_item () { rust_assert (!is_error ()); @@ -2005,16 +2008,6 @@ public: return std::move (assoc_item); } - std::unique_ptr<AssociatedItem> take_impl_item () - { - return take_assoc_item (); - } - - std::unique_ptr<AssociatedItem> take_trait_impl_item () - { - return take_assoc_item (); - } - std::unique_ptr<Type> take_type () { rust_assert (!is_error ()); diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc index 11c3297..cd6be7f 100644 --- a/gcc/rust/ast/rust-collect-lang-items.cc +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -19,6 +19,7 @@ #include "rust-collect-lang-items.h" #include "optional.h" #include "rust-ast-collector.h" +#include "rust-ast-visitor.h" #include "rust-ast.h" #include "rust-attribute-values.h" #include "rust-attributes.h" @@ -100,5 +101,13 @@ CollectLangItems::visit (AST::StructStruct &item) DefaultASTVisitor::visit (item); } +void +CollectLangItems::visit (AST::EnumItem &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-collect-lang-items.h b/gcc/rust/ast/rust-collect-lang-items.h index 39cb4be..ddb34a9 100644 --- a/gcc/rust/ast/rust-collect-lang-items.h +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -49,6 +49,7 @@ public: void visit (AST::TraitItemType &item) override; void visit (AST::Function &item) override; void visit (AST::StructStruct &item) override; + void visit (AST::EnumItem &item) override; private: template <typename T> void maybe_add_lang_item (const T &item); diff --git a/gcc/rust/ast/rust-desugar-for-loops.cc b/gcc/rust/ast/rust-desugar-for-loops.cc new file mode 100644 index 0000000..5e5cbbc --- /dev/null +++ b/gcc/rust/ast/rust-desugar-for-loops.cc @@ -0,0 +1,204 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-desugar-for-loops.h" +#include "rust-ast-visitor.h" +#include "rust-ast.h" +#include "rust-hir-map.h" +#include "rust-path.h" +#include "rust-pattern.h" +#include "rust-stmt.h" +#include "rust-expr.h" +#include "rust-ast-builder.h" + +namespace Rust { +namespace AST { + +DesugarForLoops::DesugarForLoops () {} + +void +DesugarForLoops::go (AST::Crate &crate) +{ + DefaultASTVisitor::visit (crate); +} + +static void +replace_for_loop (std::unique_ptr<Expr> &for_loop, + std::unique_ptr<Expr> &&expanded) +{ + for_loop = std::move (expanded); +} + +MatchArm +DesugarForLoops::DesugarCtx::make_match_arm (std::unique_ptr<Pattern> &&path) +{ + auto patterns = std::vector<std::unique_ptr<Pattern>> (); + patterns.emplace_back (std::move (path)); + + return MatchArm (std::move (patterns), loc); +} + +MatchCase +DesugarForLoops::DesugarCtx::make_break_arm () +{ + auto arm = make_match_arm (std::unique_ptr<Pattern> (new PathInExpression ( + builder.path_in_expression (LangItem::Kind::OPTION_NONE)))); + + auto break_expr = std::unique_ptr<Expr> ( + new BreakExpr (Lifetime::error (), nullptr, {}, loc)); + + return MatchCase (std::move (arm), std::move (break_expr)); +} + +MatchCase +DesugarForLoops::DesugarCtx::make_continue_arm () +{ + auto val = builder.identifier_pattern (DesugarCtx::continue_pattern_id); + + auto patterns = std::vector<std::unique_ptr<Pattern>> (); + patterns.emplace_back (std::move (val)); + + auto pattern_item = std::unique_ptr<TupleStructItems> ( + new TupleStructItemsNoRange (std::move (patterns))); + auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern ( + builder.path_in_expression (LangItem::Kind::OPTION_SOME), + std::move (pattern_item))); + + auto val_arm = make_match_arm (std::move (pattern)); + + auto next = builder.identifier (DesugarCtx::next_value_id); + + auto assignment = std::unique_ptr<Expr> ( + new AssignmentExpr (std::move (next), + builder.identifier (DesugarCtx::continue_pattern_id), + {}, loc)); + + return MatchCase (std::move (val_arm), std::move (assignment)); +} + +std::unique_ptr<Stmt> +DesugarForLoops::DesugarCtx::statementify (std::unique_ptr<Expr> &&expr) +{ + return std::unique_ptr<Stmt> (new ExprStmt (std::move (expr), loc, true)); +} + +std::unique_ptr<Expr> +DesugarForLoops::desugar (AST::ForLoopExpr &expr) +{ + auto ctx = DesugarCtx (expr.get_locus ()); + + auto into_iter = std::make_unique<PathInExpression> ( + ctx.builder.path_in_expression (LangItem::Kind::INTOITER_INTOITER)); + auto next = std::make_unique<PathInExpression> ( + ctx.builder.path_in_expression (LangItem::Kind::ITERATOR_NEXT)); + + // IntoIterator::into_iter(<head>) + auto into_iter_call + = ctx.builder.call (std::move (into_iter), + expr.get_iterator_expr ().clone_expr ()); + + // Iterator::next(iter) + auto next_call = ctx.builder.call ( + std::move (next), + ctx.builder.ref (ctx.builder.identifier (DesugarCtx::iter_id), true)); + + // None => break, + auto break_arm = ctx.make_break_arm (); + // Some(val) => __next = val; }, + auto continue_arm = ctx.make_continue_arm (); + + // match <next_call> { + // <continue_arm> + // <break_arm> + // } + auto match_next + = ctx.builder.match (std::move (next_call), + {std::move (continue_arm), std::move (break_arm)}); + + // let mut __next; + auto let_next = ctx.builder.let ( + ctx.builder.identifier_pattern (DesugarCtx::next_value_id, true)); + // let <pattern> = __next; + auto let_pat + = ctx.builder.let (expr.get_pattern ().clone_pattern (), nullptr, + ctx.builder.identifier (DesugarCtx::next_value_id)); + + auto loop_stmts = std::vector<std::unique_ptr<Stmt>> (); + loop_stmts.emplace_back (std::move (let_next)); + loop_stmts.emplace_back (ctx.statementify (std::move (match_next))); + loop_stmts.emplace_back (std::move (let_pat)); + loop_stmts.emplace_back ( + ctx.statementify (expr.get_loop_block ().clone_expr ())); + + // loop { + // <let_next>; + // <match_next>; + // <let_pat>; + // + // <body>; + // } + auto loop = ctx.builder.loop (std::move (loop_stmts)); + + auto mut_iter_pattern + = ctx.builder.identifier_pattern (DesugarCtx::iter_id, true); + auto match_iter + = ctx.builder.match (std::move (into_iter_call), + {ctx.builder.match_case (std::move (mut_iter_pattern), + std::move (loop))}); + + auto let_result + = ctx.builder.let (ctx.builder.identifier_pattern (DesugarCtx::result_id), + nullptr, std::move (match_iter)); + auto result_return = ctx.builder.identifier (DesugarCtx::result_id); + + return ctx.builder.block (std::move (let_result), std::move (result_return)); +} + +void +DesugarForLoops::maybe_desugar_expr (std::unique_ptr<Expr> &expr) +{ + if (expr->get_expr_kind () == AST::Expr::Kind::Loop) + { + auto &loop = static_cast<AST::BaseLoopExpr &> (*expr); + + if (loop.get_loop_kind () == AST::BaseLoopExpr::Kind::For) + { + auto &for_loop = static_cast<AST::ForLoopExpr &> (loop); + + auto desugared = desugar (for_loop); + + replace_for_loop (expr, std::move (desugared)); + } + } +} + +void +DesugarForLoops::visit (AST::BlockExpr &block) +{ + for (auto &stmt : block.get_statements ()) + if (stmt->get_stmt_kind () == AST::Stmt::Kind::Expr) + maybe_desugar_expr (static_cast<AST::ExprStmt &> (*stmt).get_expr_ptr ()); + + if (block.has_tail_expr ()) + maybe_desugar_expr (block.get_tail_expr_ptr ()); + + DefaultASTVisitor::visit (block); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-for-loops.h b/gcc/rust/ast/rust-desugar-for-loops.h new file mode 100644 index 0000000..7beb692 --- /dev/null +++ b/gcc/rust/ast/rust-desugar-for-loops.h @@ -0,0 +1,108 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_DESUGAR_FOR_LOOPS_H +#define RUST_DESUGAR_FOR_LOOPS_H + +#include "rust-ast-builder.h" +#include "rust-ast-visitor.h" +#include "rust-expr.h" + +namespace Rust { +namespace AST { + +// Desugar for-loops into a set of other AST nodes. The desugar is of the +// following form: +// +// ``` +// for <pat> in <head> <body> +// ``` +// +// becomes: +// +// ``` +// { +// let result = match ::std::iter::IntoIterator::into_iter(<head>) { +// mut iter => { +// loop { +// let mut __next; +// match ::std::iter::Iterator::next(&mut iter) { +// ::std::option::Option::Some(val) => __next = val, +// ::std::option::Option::None => break +// }; +// let <pat> = __next; +// +// <body>; +// } +// } +// }; +// result +// } +// ``` +// +// NOTE: In a perfect world, this would be an immutable visitor which would take +// ownership of the AST node and return a new one, instead of mutating this one +// in place. Nevertheless, this isn't Rust, and doing immutable visitors in C++ +// sucks, and the world isn't perfect, so we are impure and sad. +// +// NOTE: This class could eventually be removed in favor of +// an HIR desugar. This would avoid mutating the AST and would be cleaner. +// However, it requires multiple changes in the way we do typechecking and name +// resolution, as this desugar creates new bindings. Because of this, these new +// bindings need to be inserted into the name-resolution context outside of the +// name resolution pass, which is difficult. Those bindings are needed because +// of the way the typechecker is currently structured, where it will fetch name +// resolution information in order to typecheck paths - which technically isn't +// necessary. +class DesugarForLoops : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + DesugarForLoops (); + void go (AST::Crate &); + +private: + struct DesugarCtx + { + DesugarCtx (location_t loc) : builder (Builder (loc)), loc (loc) {} + + Builder builder; + location_t loc; + + MatchArm make_match_arm (std::unique_ptr<Pattern> &&pattern); + MatchCase make_break_arm (); + MatchCase make_continue_arm (); + std::unique_ptr<Stmt> statementify (std::unique_ptr<Expr> &&expr); + + constexpr static const char *continue_pattern_id = "#val"; + constexpr static const char *next_value_id = "#__next"; + constexpr static const char *iter_id = "#iter"; + constexpr static const char *result_id = "#result"; + }; + + std::unique_ptr<Expr> desugar (AST::ForLoopExpr &expr); + void maybe_desugar_expr (std::unique_ptr<Expr> &expr); + + void visit (AST::BlockExpr &) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_FOR_LOOPS_H diff --git a/gcc/rust/ast/rust-desugar-question-mark.cc b/gcc/rust/ast/rust-desugar-question-mark.cc new file mode 100644 index 0000000..4d2933b --- /dev/null +++ b/gcc/rust/ast/rust-desugar-question-mark.cc @@ -0,0 +1,167 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-desugar-question-mark.h" +#include "rust-ast-builder.h" +#include "rust-ast-visitor.h" + +namespace Rust { +namespace AST { + +DesugarQuestionMark::DesugarQuestionMark () {} + +void +DesugarQuestionMark::go (AST::Crate &crate) +{ + DesugarQuestionMark::visit (crate); +} + +void +DesugarQuestionMark::visit (ExprStmt &stmt) +{ + if (stmt.get_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation) + desugar_and_replace (stmt.get_expr_ptr ()); + + DefaultASTVisitor::visit (stmt); +} + +void +DesugarQuestionMark::visit (CallExpr &call) +{ + if (call.get_function_expr ().get_expr_kind () + == Expr::Kind::ErrorPropagation) + desugar_and_replace (call.get_function_expr_ptr ()); + + for (auto &arg : call.get_params ()) + if (arg->get_expr_kind () == Expr::Kind::ErrorPropagation) + desugar_and_replace (arg); + + DefaultASTVisitor::visit (call); +} + +void +DesugarQuestionMark::visit (LetStmt &stmt) +{ + if (stmt.has_init_expr () + && stmt.get_init_expr ().get_expr_kind () == Expr::Kind::ErrorPropagation) + desugar_and_replace (stmt.get_init_expr_ptr ()); + + DefaultASTVisitor::visit (stmt); +} + +MatchArm +make_match_arm (std::unique_ptr<Pattern> &&pattern) +{ + auto loc = pattern->get_locus (); + + auto patterns = std::vector<std::unique_ptr<Pattern>> (); + patterns.emplace_back (std::move (pattern)); + + return MatchArm (std::move (patterns), loc); +} + +MatchCase +ok_case (Builder &builder) +{ + auto val = builder.identifier_pattern ("val"); + + auto patterns = std::vector<std::unique_ptr<Pattern>> (); + patterns.emplace_back (std::move (val)); + + auto pattern_item = std::unique_ptr<TupleStructItems> ( + new TupleStructItemsNoRange (std::move (patterns))); + auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern ( + builder.path_in_expression (LangItem::Kind::RESULT_OK), + std::move (pattern_item))); + + auto arm = make_match_arm (std::move (pattern)); + + auto ret_val = builder.identifier ("val"); + + return MatchCase (std::move (arm), std::move (ret_val)); +} + +MatchCase +err_case (Builder &builder) +{ + auto val = builder.identifier_pattern ("err"); + + auto patterns = std::vector<std::unique_ptr<Pattern>> (); + patterns.emplace_back (std::move (val)); + + auto pattern_item = std::unique_ptr<TupleStructItems> ( + new TupleStructItemsNoRange (std::move (patterns))); + auto pattern = std::unique_ptr<Pattern> (new TupleStructPattern ( + builder.path_in_expression (LangItem::Kind::RESULT_ERR), + std::move (pattern_item))); + + auto arm = make_match_arm (std::move (pattern)); + + auto try_from_err = std::make_unique<PathInExpression> ( + builder.path_in_expression (LangItem::Kind::TRY_FROM_ERROR)); + auto from_from = std::make_unique<PathInExpression> ( + builder.path_in_expression (LangItem::Kind::FROM_FROM)); + + auto early_return = builder.return_expr ( + builder.call (std::move (try_from_err), + builder.call (std::move (from_from), + builder.identifier ("err")))); + + return MatchCase (std::move (arm), std::move (early_return)); +} + +std::unique_ptr<Expr> +DesugarQuestionMark::desugar (ErrorPropagationExpr &expr) +{ + auto builder = Builder (expr.get_locus ()); + + // Try::into_result(<expr>) + auto try_into = std::make_unique<PathInExpression> ( + builder.path_in_expression (LangItem::Kind::TRY_INTO_RESULT)); + auto call = builder.call (std::move (try_into), + expr.get_propagating_expr ().clone_expr ()); + + // Ok(val) => val, + auto ok_match_case = ok_case (builder); + // Err(err) => return Try::from_error(From::from(err)), + auto err_match_case = err_case (builder); + + auto cases = std::vector<MatchCase> (); + cases.emplace_back (ok_match_case); + cases.emplace_back (err_match_case); + + // match <call> { + // <ok_arm> + // <err_arm> + // } + return std::unique_ptr<MatchExpr> (new MatchExpr (std::move (call), + std::move (cases), {}, {}, + expr.get_locus ())); +} + +void +DesugarQuestionMark::desugar_and_replace (std::unique_ptr<Expr> &ptr) +{ + auto original = static_cast<ErrorPropagationExpr &> (*ptr); + auto desugared = desugar (original); + + ptr = std::move (desugared); +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-desugar-question-mark.h b/gcc/rust/ast/rust-desugar-question-mark.h new file mode 100644 index 0000000..e4c513f --- /dev/null +++ b/gcc/rust/ast/rust-desugar-question-mark.h @@ -0,0 +1,79 @@ +// Copyright (C) 2025 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_DESUGAR_QUESTION_MARK +#define RUST_DESUGAR_QUESTION_MARK + +#include "rust-ast-visitor.h" +#include "rust-expr.h" +#include "rust-stmt.h" + +namespace Rust { +namespace AST { + +// NOTE: One more complexity compare to desugaring for-loops is that we need to +// desugar every possible expression... should we do that during lowering +// instead? but would it get resolved and expanded etc? Not sure... + +// The goal of this desugar is to go from this: +// +// ``` +// <expr>? +// ``` +// +// to this: +// +// ``` +// match Try::into_result(<expr>) { +// Ok(val) => val, +// Err(err) => return Try::from_err(From::from(err)) +// } +// ``` +// +// We use lang items for almost everything, so the actual desugared code looks +// more like this: +// +// ``` +// match #[lang = "into_result"](<expr>) { +// #[lang = "Ok"](val) => val, +// #[lang = "Err"](err) => { +// return #[lang = "from_error"](#[lang ="from"](err)) +// } +// } +// ``` +class DesugarQuestionMark : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + DesugarQuestionMark (); + void go (AST::Crate &); + +private: + void desugar_and_replace (std::unique_ptr<Expr> &ptr); + std::unique_ptr<Expr> desugar (ErrorPropagationExpr &); + + void visit (AST::ExprStmt &) override; + void visit (AST::CallExpr &) override; + void visit (AST::LetStmt &) override; +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_DESUGAR_QUESTION_MARK diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 852c3f3..cff09fe 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -407,6 +407,8 @@ public: bool get_is_double_borrow () const { return double_borrow; } bool is_raw_borrow () const { return raw_borrow; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Borrow; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -437,6 +439,8 @@ public: return *main_or_left_expr; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Dereference; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -468,6 +472,11 @@ public: return *main_or_left_expr; } + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::ErrorPropagation; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -511,6 +520,8 @@ public: return *main_or_left_expr; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Negation; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -599,6 +610,11 @@ public: void visit_lhs (ASTVisitor &vis) { main_or_left_expr->accept_vis (vis); } void visit_rhs (ASTVisitor &vis) { right_expr->accept_vis (vis); } + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::ArithmeticOrLogical; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -686,6 +702,8 @@ public: ExprType get_kind () { return expr_type; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Comparison; } + /* TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2) * maybe? */ protected: @@ -774,6 +792,8 @@ public: ExprType get_kind () { return expr_type; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::LazyBoolean; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -836,6 +856,8 @@ public: return *type_to_convert_to; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::TypeCast; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -914,6 +936,8 @@ public: return *right_expr; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Assignment; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1000,6 +1024,11 @@ public: return right_expr; } + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::CompoundAssignment; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2139,6 +2168,8 @@ public: return *function; } + std::unique_ptr<Expr> &get_function_expr_ptr () { return function; } + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 2a76acc..805be8e 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -622,6 +622,8 @@ public: std::string as_string () const override; + bool is_lang_item () const { return kind == Kind::LangItem; } + // TODO: this seems kinda dodgy std::vector<PathExprSegment> &get_segments () { @@ -727,8 +729,6 @@ public: outer_attrs = std::move (new_attrs); } - NodeId get_pattern_node_id () const { return get_node_id (); } - PathExprSegment &get_final_segment () { return get_segments ().back (); } const PathExprSegment &get_final_segment () const { diff --git a/gcc/rust/ast/rust-pattern.cc b/gcc/rust/ast/rust-pattern.cc index 98fd8e5..fc7b610 100644 --- a/gcc/rust/ast/rust-pattern.cc +++ b/gcc/rust/ast/rust-pattern.cc @@ -22,7 +22,6 @@ along with GCC; see the file COPYING3. If not see #include "rust-diagnostics.h" #include "rust-ast-visitor.h" #include "rust-macro.h" -#include "rust-session-manager.h" #include "rust-lex.h" #include "rust-parse.h" #include "rust-operators.h" diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 6cbecaf..f843a79 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -19,6 +19,7 @@ #ifndef RUST_AST_STATEMENT_H #define RUST_AST_STATEMENT_H +#include "optional.h" #include "rust-ast.h" #include "rust-path.h" #include "rust-expr.h" @@ -72,6 +73,8 @@ class LetStmt : public Stmt // bool has_init_expr; std::unique_ptr<Expr> init_expr; + tl::optional<std::unique_ptr<Expr>> else_expr; + location_t locus; public: @@ -85,15 +88,18 @@ public: // Returns whether let statement has an initialisation expression. bool has_init_expr () const { return init_expr != nullptr; } + bool has_else_expr () const { return else_expr.has_value (); } std::string as_string () const override; LetStmt (std::unique_ptr<Pattern> variables_pattern, std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type, + tl::optional<std::unique_ptr<Expr>> else_expr, std::vector<Attribute> outer_attrs, location_t locus) : outer_attrs (std::move (outer_attrs)), variables_pattern (std::move (variables_pattern)), - type (std::move (type)), init_expr (std::move (init_expr)), locus (locus) + type (std::move (type)), init_expr (std::move (init_expr)), + else_expr (std::move (else_expr)), locus (locus) {} // Copy constructor with clone @@ -107,6 +113,9 @@ public: // guard to prevent null dereference (always required) if (other.init_expr != nullptr) init_expr = other.init_expr->clone_expr (); + if (other.else_expr.has_value ()) + else_expr = other.else_expr.value ()->clone_expr (); + if (other.type != nullptr) type = other.type->clone_type (); } @@ -128,6 +137,12 @@ public: init_expr = other.init_expr->clone_expr (); else init_expr = nullptr; + + if (other.else_expr != nullptr) + else_expr = other.else_expr.value ()->clone_expr (); + else + else_expr = tl::nullopt; + if (other.type != nullptr) type = other.type->clone_type (); else @@ -162,12 +177,24 @@ public: return *init_expr; } + Expr &get_else_expr () + { + rust_assert (has_else_expr ()); + return *else_expr.value (); + } + std::unique_ptr<Expr> &get_init_expr_ptr () { rust_assert (has_init_expr ()); return init_expr; } + std::unique_ptr<Expr> &get_else_expr_ptr () + { + rust_assert (has_else_expr ()); + return else_expr.value (); + } + Pattern &get_pattern () { rust_assert (variables_pattern != nullptr); |