diff options
Diffstat (limited to 'gcc/rust/ast')
25 files changed, 2146 insertions, 915 deletions
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc index e76d0de..13126b4 100644 --- a/gcc/rust/ast/rust-ast-builder-type.cc +++ b/gcc/rust/ast/rust-ast-builder-type.cc @@ -20,7 +20,6 @@ #include "rust-ast-builder.h" #include "rust-ast-full.h" #include "rust-common.h" -#include "rust-make-unique.h" namespace Rust { namespace AST { diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 529c686..08c52b1 100644 --- a/gcc/rust/ast/rust-ast-builder.cc +++ b/gcc/rust/ast/rust-ast-builder.cc @@ -17,15 +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 "rust-make-unique.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 { @@ -35,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 { @@ -43,19 +70,56 @@ Builder::call (std::unique_ptr<Expr> &&path, } std::unique_ptr<Expr> +Builder::call (std::unique_ptr<Expr> &&path, std::unique_ptr<Expr> &&arg) const +{ + auto args = std::vector<std::unique_ptr<Expr>> (); + args.emplace_back (std::move (arg)); + + return call (std::move (path), std::move (args)); +} + +std::unique_ptr<Expr> Builder::array (std::vector<std::unique_ptr<Expr>> &&members) const { - auto elts = Rust::make_unique<ArrayElemsValues> (std::move (members), loc); + auto elts = std::make_unique<ArrayElemsValues> (std::move (members), loc); return std::unique_ptr<Expr> (new ArrayExpr (std::move (elts), {}, {}, loc)); } 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)); } +std::unique_ptr<Pattern> +Builder::identifier_pattern (std::string name, bool mut) const +{ + return std::unique_ptr<Pattern> ( + new IdentifierPattern (name, loc, false, mut)); +} + std::unique_ptr<Expr> Builder::tuple_idx (std::string receiver, int idx) const { @@ -63,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> (tl::nullopt, 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 { @@ -83,12 +183,27 @@ Builder::type_path_segment (std::string seg) const } std::unique_ptr<TypePathSegment> -Builder::generic_type_path_segment (std::string seg, GenericArgs args) const +Builder::type_path_segment (LangItem::Kind lang_item) const +{ + return std::unique_ptr<TypePathSegment> ( + new TypePathSegment (lang_item, loc)); +} + +std::unique_ptr<TypePathSegment> +Builder::type_path_segment_generic (std::string seg, GenericArgs args) const { return std::unique_ptr<TypePathSegment> ( new TypePathSegmentGeneric (PathIdentSegment (seg, loc), false, args, loc)); } +std::unique_ptr<TypePathSegment> +Builder::type_path_segment_generic (LangItem::Kind lang_item, + GenericArgs args) const +{ + return std::unique_ptr<TypePathSegment> ( + new TypePathSegmentGeneric (lang_item, args, loc)); +} + std::unique_ptr<Type> Builder::single_type_path (std::string type) const { @@ -99,40 +214,146 @@ Builder::single_type_path (std::string type) const } std::unique_ptr<Type> +Builder::single_type_path (LangItem::Kind lang_item) const +{ + return std::unique_ptr<Type> (new TypePath (lang_item, {}, loc)); +} + +std::unique_ptr<Type> Builder::single_generic_type_path (std::string type, GenericArgs args) const { auto segments = std::vector<std::unique_ptr<TypePathSegment>> (); - segments.emplace_back (generic_type_path_segment (type, args)); + segments.emplace_back (type_path_segment_generic (type, args)); return std::unique_ptr<Type> (new TypePath (std::move (segments), loc)); } +std::unique_ptr<Type> +Builder::single_generic_type_path (LangItem::Kind lang_item, + GenericArgs args) const +{ + auto segments = std::vector<std::unique_ptr<TypePathSegment>> (); + segments.emplace_back (type_path_segment_generic (lang_item, args)); + + return std::unique_ptr<Type> (new TypePath (std::move (segments), loc)); +} + +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 type_path (std::move (segments)); +} + +TypePath +Builder::type_path (std::string type) const +{ + return type_path (type_path_segment (type)); +} + +TypePath +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); } -std::unique_ptr<Expr> +PathInExpression +Builder::path_in_expression (LangItem::Kind lang_item) const +{ + return PathInExpression (lang_item, {}, loc); +} + +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>> (); + + if (stmt) + stmts.emplace_back (std::move (*stmt)); + + return block (std::move (stmts), std::move (tail_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), {}, + {}, tl::nullopt, 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> @@ -151,6 +372,37 @@ Builder::deref (std::unique_ptr<Expr> &&of) const } 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, + std::vector<StructField> &&fields) +{ + auto is_unit = fields.empty (); + + return std::unique_ptr<Stmt> ( + new StructStruct (std::move (fields), struct_name, std::move (generics), + WhereClause::create_empty (), is_unit, + Visibility::create_private (), {}, loc)); +} + +std::unique_ptr<Expr> Builder::struct_expr_struct (std::string struct_name) const { return std::unique_ptr<Expr> ( @@ -162,9 +414,16 @@ Builder::struct_expr ( std::string struct_name, std::vector<std::unique_ptr<StructExprField>> &&fields) const { + return struct_expr (path_in_expression ({struct_name}), std::move (fields)); +} + +std::unique_ptr<Expr> +Builder::struct_expr ( + PathInExpression struct_name, + std::vector<std::unique_ptr<StructExprField>> &&fields) const +{ return std::unique_ptr<Expr> ( - new StructExprStructFields (path_in_expression ({struct_name}), - std::move (fields), loc)); + new StructExprStructFields (struct_name, std::move (fields), loc)); } std::unique_ptr<StructExprField> @@ -189,6 +448,81 @@ 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 +{ + return std::unique_ptr<Path> (new PathInExpression (kind, {}, loc)); +} + +std::unique_ptr<Expr> +Builder::match (std::unique_ptr<Expr> &&scrutinee, + std::vector<MatchCase> &&cases) +{ + return std::unique_ptr<Expr> ( + new MatchExpr (std::move (scrutinee), std::move (cases), {}, {}, loc)); +} + +MatchArm +Builder::match_arm (std::unique_ptr<Pattern> &&pattern) +{ + auto patterns = std::vector<std::unique_ptr<Pattern>> (); + patterns.emplace_back (std::move (pattern)); + + return MatchArm (std::move (patterns), loc); +} + +MatchCase +Builder::match_case (std::unique_ptr<Pattern> &&pattern, + std::unique_ptr<Expr> &&expr) +{ + return MatchCase (match_arm (std::move (pattern)), std::move (expr)); +} + +std::unique_ptr<Expr> +Builder::loop (std::vector<std::unique_ptr<Stmt>> &&stmts) +{ + auto block_expr = block (std::move (stmts), nullptr); + + 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> Builder::new_type (Type &type) { @@ -213,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 (); @@ -224,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 bad79d0..41ce118 100644 --- a/gcc/rust/ast/rust-ast-builder.h +++ b/gcc/rust/ast/rust-ast-builder.h @@ -20,10 +20,45 @@ #define AST_BUILDER_H #include "rust-ast-full.h" +#include "rust-expr.h" +#include "rust-ast.h" +#include "rust-item.h" +#include "rust-operators.h" namespace Rust { namespace AST { +template <typename T> +std::vector<std::unique_ptr<T>> +vec (std::unique_ptr<T> &&t) +{ + auto v = std::vector<std::unique_ptr<T>> (); + + v.emplace_back (std::move (t)); + + return v; +} + +template <typename T> +std::vector<std::unique_ptr<T>> +vec (std::unique_ptr<T> &&t1, std::unique_ptr<T> &&t2) +{ + auto v = std::vector<std::unique_ptr<T>> (); + + v.emplace_back (std::move (t1)); + v.emplace_back (std::move (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 @@ -33,15 +68,28 @@ 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, + bool mut = false) const; /* 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; @@ -49,23 +97,45 @@ 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<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; /** * Create an array expression (`[member0, member1, member2]`) @@ -73,42 +143,107 @@ 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; /* And similarly for type path segments */ std::unique_ptr<TypePathSegment> type_path_segment (std::string seg) const; + std::unique_ptr<TypePathSegment> + type_path_segment (LangItem::Kind lang_item) const; std::unique_ptr<TypePathSegment> - generic_type_path_segment (std::string seg, GenericArgs args) const; + type_path_segment_generic (std::string seg, GenericArgs args) const; + std::unique_ptr<TypePathSegment> + type_path_segment_generic (LangItem::Kind lang_item, GenericArgs args) const; /* Create a Type from a single string - the most basic kind of type in our AST */ std::unique_ptr<Type> single_type_path (std::string type) const; + std::unique_ptr<Type> single_type_path (LangItem::Kind lang_item) const; std::unique_ptr<Type> single_generic_type_path (std::string type, GenericArgs args) const; + 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, + std::vector<std::unique_ptr<GenericParam>> &&generics, + std::vector<StructField> &&fields); /* Create a struct expression for unit structs (`S`) */ std::unique_ptr<Expr> struct_expr_struct (std::string struct_name) const; /** * Create an expression for struct instantiation with fields (`S { a, b: c }`) + * 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, std::vector<std::unique_ptr<StructExprField>> &&fields) const; + std::unique_ptr<Expr> + struct_expr (PathInExpression struct_name, + std::vector<std::unique_ptr<StructExprField>> &&fields) const; /* Create a field expression for struct instantiation (`field_name: value`) */ std::unique_ptr<StructExprField> @@ -121,13 +256,43 @@ 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; + + /* Create match expressions and their components */ + std::unique_ptr<Expr> match (std::unique_ptr<Expr> &&scrutinee, + std::vector<MatchCase> &&cases); + MatchArm match_arm (std::unique_ptr<Pattern> &&pattern); + MatchCase match_case (std::unique_ptr<Pattern> &&pattern, + std::unique_ptr<Expr> &&expr); + + /* 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 2022668..c850e96 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" @@ -251,29 +254,6 @@ TokenCollector::visit (Visibility &vis) } void -TokenCollector::visit (NamedFunctionParam ¶m) -{ - auto name = param.get_name (); - if (!param.is_variadic ()) - { - push ( - Rust::Token::make_identifier (param.get_locus (), std::move (name))); - push (Rust::Token::make (COLON, UNDEF_LOCATION)); - visit (param.get_type ()); - } - else - { - if (name != "") - { - push (Rust::Token::make_identifier (param.get_locus (), - std::move (name))); - push (Rust::Token::make (COLON, UNDEF_LOCATION)); - } - push (Rust::Token::make (ELLIPSIS, UNDEF_LOCATION)); - } -} - -void TokenCollector::visit (std::vector<std::unique_ptr<GenericParam>> ¶ms) { push (Rust::Token::make (LEFT_ANGLE, UNDEF_LOCATION)); @@ -511,7 +491,7 @@ TokenCollector::visit (ConstGenericParam ¶m) if (param.has_default_value ()) { push (Rust::Token::make (EQUAL, UNDEF_LOCATION)); - visit (param.get_default_value ()); + visit (param.get_default_value_unchecked ()); } } @@ -553,25 +533,24 @@ 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 ())); - visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION); -} + return; + } -void -TokenCollector::visit (RegularPath &path) -{ - // FIXME: We probably want to have a proper implementation here, and call this - // function from things like the PathInExpression visitor -} + if (path.opening_scope_resolution ()) + push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); -void -TokenCollector::visit (LangItemPath &path) -{ - // TODO: Implement proper token collection for lang item paths + visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION); } void @@ -579,10 +558,14 @@ TokenCollector::visit (TypePathSegment &segment) { // Syntax: // PathIdentSegment - auto ident_segment = segment.get_ident_segment (); - auto id = ident_segment.as_string (); - push ( - Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); + + auto locus = segment.is_lang_item () + ? segment.get_locus () + : segment.get_ident_segment ().get_locus (); + auto segment_string = segment.is_lang_item () + ? LangItem::PrettyString (segment.get_lang_item ()) + : segment.get_ident_segment ().as_string (); + push (Rust::Token::make_identifier (locus, std::move (segment_string))); } void @@ -594,10 +577,13 @@ TokenCollector::visit (TypePathSegmentGeneric &segment) // `<` `>` // | `<` ( GenericArg `,` )* GenericArg `,`? `>` - auto ident_segment = segment.get_ident_segment (); - auto id = ident_segment.as_string (); - push ( - Rust::Token::make_identifier (ident_segment.get_locus (), std::move (id))); + auto locus = segment.is_lang_item () + ? segment.get_locus () + : segment.get_ident_segment ().get_locus (); + auto segment_string = segment.is_lang_item () + ? LangItem::PrettyString (segment.get_lang_item ()) + : segment.get_ident_segment ().as_string (); + push (Rust::Token::make_identifier (locus, std::move (segment_string))); if (segment.get_separating_scope_resolution ()) push (Rust::Token::make (SCOPE_RESOLUTION, UNDEF_LOCATION)); @@ -653,8 +639,6 @@ TokenCollector::visit (GenericArg &arg) push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path))); } break; - case GenericArg::Kind::Error: - rust_unreachable (); } } @@ -711,19 +695,19 @@ TokenCollector::visit (TypePath &path) void TokenCollector::visit (PathIdentSegment &segment) { - if (segment.is_super_segment ()) + if (segment.is_super_path_seg ()) { push (Rust::Token::make (SUPER, segment.get_locus ())); } - else if (segment.is_crate_segment ()) + else if (segment.is_crate_path_seg ()) { push (Rust::Token::make (CRATE, segment.get_locus ())); } - else if (segment.is_lower_self ()) + else if (segment.is_lower_self_seg ()) { push (Rust::Token::make (SELF, segment.get_locus ())); } - else if (segment.is_big_self ()) + else if (segment.is_big_self_seg ()) { push (Rust::Token::make (SELF_ALIAS, segment.get_locus ())); } @@ -1293,7 +1277,7 @@ TokenCollector::visit (ContinueExpr &expr) { push (Rust::Token::make (CONTINUE, expr.get_locus ())); if (expr.has_label ()) - visit (expr.get_label ()); + visit (expr.get_label_unchecked ()); } void @@ -1301,7 +1285,7 @@ TokenCollector::visit (BreakExpr &expr) { push (Rust::Token::make (BREAK, expr.get_locus ())); if (expr.has_label ()) - visit (expr.get_label ()); + visit (expr.get_label_unchecked ()); if (expr.has_break_expr ()) visit (expr.get_break_expr ()); } @@ -1536,6 +1520,47 @@ void TokenCollector::visit (InlineAsm &expr) {} +void +TokenCollector::visit (LlvmInlineAsm &expr) +{ + push (Rust::Token::make_identifier (expr.get_locus (), "llvm_asm")); + push (Rust::Token::make (EXCLAM, expr.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + for (auto &template_str : expr.get_templates ()) + push (Rust::Token::make_string (template_str.get_locus (), + std::move (template_str.symbol))); + + push (Rust::Token::make (COLON, expr.get_locus ())); + for (auto output : expr.get_outputs ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (output.constraint))); + visit (output.expr); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (COLON, expr.get_locus ())); + for (auto input : expr.get_inputs ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (input.constraint))); + visit (input.expr); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (COLON, expr.get_locus ())); + for (auto &clobber : expr.get_clobbers ()) + { + push (Rust::Token::make_string (expr.get_locus (), + std::move (clobber.symbol))); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + // Dump options + + push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ())); +} + // rust-item.h void @@ -2499,10 +2524,7 @@ TokenCollector::visit (StructPattern &pattern) void TokenCollector::visit (TupleStructItemsNoRange &pattern) { - for (auto &pat : pattern.get_patterns ()) - { - visit (pat); - } + visit_items_joined_by_separator (pattern.get_patterns ()); } void @@ -2605,6 +2627,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-collector.h b/gcc/rust/ast/rust-ast-collector.h index 32a5bd3..f45e3cc 100644 --- a/gcc/rust/ast/rust-ast-collector.h +++ b/gcc/rust/ast/rust-ast-collector.h @@ -210,7 +210,6 @@ public: void visit (TupleField &field); void visit (StructField &field); void visit (SimplePathSegment &segment); - void visit (NamedFunctionParam ¶m); void visit (MacroRule &rule); void visit (WhereClause &rule); void visit (std::vector<LifetimeParam> &for_lifetimes); @@ -234,8 +233,6 @@ public: void visit (PathExprSegment &segment); void visit (PathIdentSegment &segment); void visit (PathInExpression &path); - void visit (RegularPath &path); - void visit (LangItemPath &path); void visit (TypePathSegment &segment); void visit (TypePathSegmentGeneric &segment); void visit (TypePathSegmentFunction &segment); @@ -306,6 +303,7 @@ public: void visit (AwaitExpr &expr); void visit (AsyncBlockExpr &expr); void visit (InlineAsm &expr); + void visit (LlvmInlineAsm &expr); // rust-item.h void visit (TypeParam ¶m); void visit (LifetimeWhereClauseItem &item); diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 80d217e..9359248 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -202,7 +202,6 @@ class TraitImpl; class ExternalItem; class ExternalTypeItem; class ExternalStaticItem; -class NamedFunctionParam; class ExternBlock; // rust-macro.h diff --git a/gcc/rust/ast/rust-ast-visitor.cc b/gcc/rust/ast/rust-ast-visitor.cc index 8f53e52..b6833f6 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -82,26 +82,17 @@ DefaultASTVisitor::visit (AST::ConstGenericParam &const_param) if (const_param.has_type ()) visit (const_param.get_type ()); if (const_param.has_default_value ()) - visit (const_param.get_default_value ()); + visit (const_param.get_default_value_unchecked ()); } void -DefaultASTVisitor::visit (AST::RegularPath &path) -{ - for (auto &segment : path.get_segments ()) - visit (segment); -} - -void -DefaultASTVisitor::visit (AST::LangItemPath &path) -{} - -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 @@ -117,7 +108,8 @@ DefaultASTVisitor::visit (GenericArgsBinding &binding) void DefaultASTVisitor::visit (AST::TypePathSegmentGeneric &segment) { - visit (segment.get_generic_args ()); + if (segment.has_generic_args ()) + visit (segment.get_generic_args ()); } void @@ -401,6 +393,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 ()) @@ -412,6 +405,7 @@ DefaultASTVisitor::visit (AST::StructExprStructBase &expr) { visit_outer_attrs (expr); visit_inner_attrs (expr); + visit (expr.get_struct_name ()); visit (expr.get_struct_base ()); } @@ -484,7 +478,8 @@ void DefaultASTVisitor::visit (AST::ContinueExpr &expr) { visit_outer_attrs (expr); - visit (expr.get_label ()); + if (expr.has_label ()) + visit (expr.get_label_unchecked ()); } void @@ -492,7 +487,7 @@ DefaultASTVisitor::visit (AST::BreakExpr &expr) { visit_outer_attrs (expr); if (expr.has_label ()) - visit (expr.get_label ()); + visit (expr.get_label_unchecked ()); if (expr.has_break_expr ()) visit (expr.get_break_expr ()); @@ -566,7 +561,8 @@ void DefaultASTVisitor::visit (AST::LoopExpr &expr) { visit_outer_attrs (expr); - visit (expr.get_loop_label ()); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); visit (expr.get_loop_block ()); } @@ -574,8 +570,9 @@ void DefaultASTVisitor::visit (AST::WhileLoopExpr &expr) { visit_outer_attrs (expr); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); visit (expr.get_predicate_expr ()); - visit (expr.get_loop_label ()); visit (expr.get_loop_block ()); } @@ -585,8 +582,8 @@ DefaultASTVisitor::visit (AST::WhileLetLoopExpr &expr) visit_outer_attrs (expr); for (auto &pattern : expr.get_patterns ()) visit (pattern); - visit (expr.get_scrutinee_expr ()); visit (expr.get_loop_label ()); + visit (expr.get_scrutinee_expr ()); visit (expr.get_loop_block ()); } @@ -596,7 +593,8 @@ DefaultASTVisitor::visit (AST::ForLoopExpr &expr) visit_outer_attrs (expr); visit (expr.get_pattern ()); visit (expr.get_iterator_expr ()); - visit (expr.get_loop_label ()); + if (expr.has_loop_label ()) + visit (expr.get_loop_label ()); visit (expr.get_loop_block ()); } @@ -717,6 +715,16 @@ DefaultASTVisitor::visit (AST::InlineAsm &expr) } void +DefaultASTVisitor::visit (AST::LlvmInlineAsm &expr) +{ + for (auto &output : expr.get_outputs ()) + visit (output.expr); + + for (auto &input : expr.get_inputs ()) + visit (input.expr); +} + +void DefaultASTVisitor::visit (AST::TypeParam ¶m) { visit_outer_attrs (param); @@ -820,10 +828,18 @@ DefaultASTVisitor::visit (AST::UseTreeRebind &use_tree) void DefaultASTVisitor::visit (AST::UseDeclaration &use_decl) { + visit (use_decl.get_visibility ()); visit (use_decl.get_tree ()); } void +DefaultASTVisitor::visit_function_params (AST::Function &function) +{ + for (auto ¶m : function.get_function_params ()) + visit (param); +} + +void DefaultASTVisitor::visit (AST::Function &function) { visit_outer_attrs (function); @@ -831,10 +847,9 @@ DefaultASTVisitor::visit (AST::Function &function) visit (function.get_qualifiers ()); for (auto &generic : function.get_generic_params ()) visit (generic); - if (function.has_self_param ()) - visit (function.get_self_param ()); - for (auto ¶m : function.get_function_params ()) - visit (param); + + visit_function_params (function); + if (function.has_return_type ()) visit (function.get_return_type ()); if (function.has_where_clause ()) @@ -997,6 +1012,8 @@ DefaultASTVisitor::visit (AST::Trait &trait) visit_inner_attrs (trait); + visit (trait.get_implicit_self ()); + for (auto &generic : trait.get_generic_params ()) visit (generic); @@ -1037,6 +1054,7 @@ DefaultASTVisitor::visit (AST::TraitImpl &impl) if (impl.has_where_clause ()) visit (impl.get_where_clause ()); visit (impl.get_type ()); + visit (impl.get_trait_path ()); visit_inner_attrs (impl); for (auto &item : impl.get_impl_items ()) visit (item); @@ -1058,14 +1076,6 @@ DefaultASTVisitor::visit (AST::ExternalStaticItem &item) } void -DefaultASTVisitor::visit (AST::NamedFunctionParam ¶m) -{ - visit_outer_attrs (param); - if (!param.is_variadic ()) - visit (param.get_type ()); -} - -void DefaultASTVisitor::visit (AST::ExternBlock &block) { visit_outer_attrs (block); @@ -1453,33 +1463,33 @@ DefaultASTVisitor::visit (AST::VariadicParam ¶m) void ContextualASTVisitor::visit (AST::Crate &crate) { - push_context (Context::CRATE); + ctx.enter (Kind::CRATE); DefaultASTVisitor::visit (crate); - pop_context (); + ctx.exit (); } void ContextualASTVisitor::visit (AST::InherentImpl &impl) { - push_context (Context::INHERENT_IMPL); + ctx.enter (Kind::INHERENT_IMPL); DefaultASTVisitor::visit (impl); - pop_context (); + ctx.exit (); } void ContextualASTVisitor::visit (AST::TraitImpl &impl) { - push_context (Context::TRAIT_IMPL); + ctx.enter (Kind::TRAIT_IMPL); DefaultASTVisitor::visit (impl); - pop_context (); + ctx.exit (); } void ContextualASTVisitor::visit (AST::Trait &trait) { - push_context (Context::TRAIT); + ctx.enter (Kind::TRAIT); DefaultASTVisitor::visit (trait); - pop_context (); + ctx.exit (); } } // namespace AST diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index 50b9301..b1fc504 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -26,6 +26,7 @@ #include "rust-item.h" #include "rust-path.h" #include "rust-system.h" +#include "rust-stacked-contexts.h" namespace Rust { namespace AST { @@ -59,8 +60,6 @@ public: // virtual void visit(TraitImplItem& trait_impl_item) = 0; // rust-path.h - virtual void visit (RegularPath &path) = 0; - virtual void visit (LangItemPath &path) = 0; virtual void visit (PathInExpression &path) = 0; virtual void visit (TypePathSegment &segment) = 0; virtual void visit (TypePathSegmentGeneric &segment) = 0; @@ -132,6 +131,7 @@ public: virtual void visit (AwaitExpr &expr) = 0; virtual void visit (AsyncBlockExpr &expr) = 0; virtual void visit (InlineAsm &expr) = 0; + virtual void visit (LlvmInlineAsm &expr) = 0; // rust-item.h virtual void visit (TypeParam ¶m) = 0; @@ -242,6 +242,8 @@ public: class DefaultASTVisitor : public ASTVisitor { public: + virtual void visit_function_params (AST::Function &function); + virtual void visit (AST::Crate &crate); virtual void visit (AST::Token &tok) override; @@ -251,8 +253,6 @@ public: virtual void visit (AST::Lifetime &lifetime) override; virtual void visit (AST::LifetimeParam &lifetime_param) override; virtual void visit (AST::ConstGenericParam &const_param) override; - virtual void visit (AST::RegularPath &path) override; - virtual void visit (AST::LangItemPath &path) override; virtual void visit (AST::PathInExpression &path) override; virtual void visit (AST::TypePathSegment &segment) override; virtual void visit (AST::TypePathSegmentGeneric &segment) override; @@ -317,6 +317,7 @@ public: virtual void visit (AST::AwaitExpr &expr) override; virtual void visit (AST::AsyncBlockExpr &expr) override; virtual void visit (InlineAsm &expr) override; + virtual void visit (LlvmInlineAsm &expr) override; virtual void visit (AST::TypeParam ¶m) override; virtual void visit (AST::LifetimeWhereClauseItem &item) override; @@ -427,7 +428,6 @@ public: virtual void visit (AST::WhereClause &where); virtual void visit (AST::StructField &field); virtual void visit (AST::TupleField &field); - virtual void visit (AST::NamedFunctionParam ¶m); virtual void visit (AST::MacroRule &rule); virtual void visit (AST::MacroInvocData &data); virtual void visit (AST::MacroTranscriber &transcriber); @@ -452,7 +452,7 @@ public: class ContextualASTVisitor : public DefaultASTVisitor { protected: - enum class Context + enum class Kind { FUNCTION, INHERENT_IMPL, @@ -461,6 +461,7 @@ protected: MODULE, CRATE, }; + using DefaultASTVisitor::visit; virtual void visit (AST::Crate &crate) override; @@ -476,11 +477,7 @@ protected: DefaultASTVisitor::visit (item); } - std::vector<Context> context; - - void push_context (Context ctx) { context.push_back (ctx); } - - void pop_context () { context.pop_back (); } + StackedContexts<Kind> ctx; }; } // namespace AST diff --git a/gcc/rust/ast/rust-ast.cc b/gcc/rust/ast/rust-ast.cc index 1d52352..4e82be4 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -272,8 +272,8 @@ Attribute::get_traits_to_derive () case AST::MetaItem::ItemKind::Word: { auto word = static_cast<AST::MetaWord *> (meta_item); // Convert current word to path - current - = make_unique<AST::MetaItemPath> (AST::MetaItemPath ( + current = std::make_unique<AST::MetaItemPath> ( + AST::MetaItemPath ( AST::SimplePath (word->get_ident ()))); auto path = static_cast<AST::MetaItemPath *> (current.get ()); @@ -1068,7 +1068,7 @@ Function::Function (Function const &other) : VisItem (other), ExternalItem (other.get_node_id ()), qualifiers (other.qualifiers), function_name (other.function_name), where_clause (other.where_clause), locus (other.locus), - is_default (other.is_default), + has_default (other.has_default), is_external_function (other.is_external_function) { // guard to prevent null dereference (always required) @@ -1100,7 +1100,7 @@ Function::operator= (Function const &other) // visibility = other.visibility->clone_visibility(); // outer_attrs = other.outer_attrs; locus = other.locus; - is_default = other.is_default; + has_default = other.has_default; is_external_function = other.is_external_function; // guard to prevent null dereference (always required) @@ -1631,7 +1631,7 @@ ContinueExpr::as_string () const std::string str ("continue "); if (has_label ()) - str += label.as_string (); + str += get_label_unchecked ().as_string (); return str; } @@ -2095,7 +2095,7 @@ WhileLoopExpr::as_string () const if (!has_loop_label ()) str += "none"; else - str += loop_label.as_string (); + str += get_loop_label ().as_string (); str += "\n Conditional expr: " + condition->as_string (); @@ -2115,7 +2115,7 @@ WhileLetLoopExpr::as_string () const if (!has_loop_label ()) str += "none"; else - str += loop_label.as_string (); + str += get_loop_label ().as_string (); str += "\n Match arm patterns: "; if (match_arm_patterns.empty ()) @@ -2146,7 +2146,7 @@ LoopExpr::as_string () const if (!has_loop_label ()) str += "none"; else - str += loop_label.as_string (); + str += get_loop_label ().as_string (); str += "\n Loop block: " + loop_block->as_string (); @@ -2183,7 +2183,7 @@ BreakExpr::as_string () const std::string str ("break "); if (has_label ()) - str += label.as_string () + " "; + str += get_label_unchecked ().as_string () + " "; if (has_break_expr ()) str += break_expr->as_string (); @@ -2485,9 +2485,6 @@ MacroMatchRepetition::as_string () const std::string Lifetime::as_string () const { - if (is_error ()) - return "error lifetime"; - switch (lifetime_type) { case NAMED: @@ -2545,7 +2542,7 @@ ForLoopExpr::as_string () const if (!has_loop_label ()) str += "none"; else - str += loop_label.as_string (); + str += get_loop_label ().as_string (); str += "\n Pattern: " + pattern->as_string (); @@ -2612,7 +2609,7 @@ ReferenceType::as_string () const std::string str ("&"); if (has_lifetime ()) - str += lifetime.as_string () + " "; + str += get_lifetime ().as_string () + " "; if (has_mut) str += "mut "; @@ -2998,22 +2995,6 @@ ExternalStaticItem::as_string () const } std::string -NamedFunctionParam::as_string () const -{ - std::string str = append_attributes (outer_attrs, OUTER); - - if (has_name ()) - str += "\n" + name; - - if (is_variadic ()) - str += "..."; - else - str += "\n Type: " + param_type->as_string (); - - return str; -} - -std::string TraitItemConst::as_string () const { // TODO: rewrite to work with non-linearisable exprs @@ -3086,7 +3067,7 @@ SelfParam::as_string () const else if (has_lifetime ()) { // ref and lifetime - std::string str = "&" + lifetime.as_string () + " "; + std::string str = "&" + get_lifetime ().as_string () + " "; if (is_mut) str += "mut "; @@ -4286,7 +4267,7 @@ BlockExpr::normalize_tail_expr () if (!stmt.is_semicolon_followed ()) { - expr = std::move (stmt.take_expr ()); + expr = stmt.take_expr (); statements.pop_back (); } } @@ -4670,6 +4651,12 @@ InlineAsm::accept_vis (ASTVisitor &vis) } void +LlvmInlineAsm::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void TypeParam::accept_vis (ASTVisitor &vis) { vis.visit (*this); diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 42ad011..aa6ad50 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -57,6 +57,11 @@ public: bool empty () const { return ident.empty (); } + bool operator== (const Identifier &other) const + { + return ident == other.ident; + } + private: std::string ident; location_t loc; @@ -70,16 +75,6 @@ namespace AST { class ASTVisitor; using AttrVec = std::vector<Attribute>; -// The available kinds of AST Nodes -enum class Kind -{ - UNKNOWN, - MODULE, - MACRO_RULES_DEFINITION, - MACRO_INVOCATION, - IDENTIFIER, -}; - class Visitable { public: @@ -87,20 +82,6 @@ public: virtual void accept_vis (ASTVisitor &vis) = 0; }; -// Abstract base class for all AST elements -class Node : public Visitable -{ -public: - /** - * Get the kind of Node this is. This is used to differentiate various AST - * elements with very little overhead when extracting the derived type - * through static casting is not necessary. - */ - // FIXME: Mark this as `= 0` in the future to make sure every node - // implements it - virtual Kind get_ast_kind () const { return Kind::UNKNOWN; } -}; - // Delimiter types - used in macros and whatever. enum DelimType { @@ -681,6 +662,9 @@ public: // Returns whether the attribute is considered an "empty" attribute. bool is_empty () const { return attr_input == nullptr && path.is_empty (); } + // Returns whether the attribute has no input + bool empty_input () const { return !attr_input; } + location_t get_locus () const { return locus; } AttrInput &get_attr_input () const { return *attr_input; } @@ -1039,6 +1023,7 @@ public: } DelimType get_delim_type () const { return delim_type; } + location_t get_locus () const { return locus; } }; /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr @@ -1092,7 +1077,7 @@ class MetaListNameValueStr; /* Base statement abstract class. Note that most "statements" are not allowed * in top-level module scope - only a subclass of statements called "items" * are. */ -class Stmt : public Node +class Stmt : public Visitable { public: enum class Kind @@ -1141,6 +1126,28 @@ protected: class Item : public Stmt { public: + enum class Kind + { + MacroRulesDefinition, + MacroInvocation, + Module, + ExternCrate, + UseDeclaration, + Function, + TypeAlias, + Struct, + EnumItem, + Enum, + Union, + ConstantItem, + StaticItem, + Trait, + Impl, + ExternBlock, + }; + + virtual Kind get_item_kind () const = 0; + // Unique pointer custom clone function std::unique_ptr<Item> clone_item () const { @@ -1221,14 +1228,65 @@ public: { return outer_attrs; } + + virtual Item::Kind get_item_kind () const override = 0; }; + // forward decl of ExprWithoutBlock class ExprWithoutBlock; // Base expression AST node - abstract -class Expr : public Node +class Expr : public Visitable { public: + enum class Kind + { + PathInExpression, + QualifiedPathInExpression, + Literal, + Operator, + Grouped, + Array, + ArrayIndex, + Tuple, + TupleIndex, + Struct, + Call, + MethodCall, + FieldAccess, + Closure, + Block, + Continue, + Break, + Range, + Box, + Return, + UnsafeBlock, + Loop, + If, + IfLet, + Match, + Await, + AsyncBlock, + InlineAsm, + LlvmInlineAsm, + Identifier, + FormatArgs, + MacroInvocation, + Borrow, + Dereference, + ErrorPropagation, + Negation, + ArithmeticOrLogical, + Comparison, + LazyBoolean, + TypeCast, + Assignment, + CompoundAssignment, + }; + + virtual Kind get_expr_kind () const = 0; + // Unique pointer custom clone function std::unique_ptr<Expr> clone_expr () const { @@ -1343,7 +1401,7 @@ public: outer_attrs = std::move (new_attrs); } - Kind get_ast_kind () const override { return Kind::IDENTIFIER; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Identifier; } protected: // Clone method implementation @@ -1410,7 +1468,7 @@ protected: class TraitBound; // Base class for types as represented in AST - abstract -class Type : public Node +class Type : public Visitable { public: // Unique pointer custom clone function @@ -1539,17 +1597,9 @@ public: lifetime_name (std::move (name)), locus (locus) {} - // Creates an "error" lifetime. - static Lifetime error () { return Lifetime (NAMED, ""); } - static Lifetime elided () { return Lifetime (WILDCARD, ""); } // Returns true if the lifetime is in an error state. - bool is_error () const - { - return lifetime_type == NAMED && lifetime_name.empty (); - } - std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; @@ -1640,15 +1690,6 @@ public: // Returns whether the lifetime param has an outer attribute. bool has_outer_attribute () const { return !outer_attrs.empty (); } - // Creates an error state lifetime param. - static LifetimeParam create_error () - { - return LifetimeParam (Lifetime::error (), {}, {}, UNDEF_LOCATION); - } - - // Returns whether the lifetime param is in an error state. - bool is_error () const { return lifetime.is_error (); } - // Constructor LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds, AST::AttrVec outer_attrs, location_t locus) @@ -1948,13 +1989,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 ()); @@ -1967,16 +2001,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 ()); @@ -2078,6 +2102,19 @@ template <> struct less<Rust::Identifier> return lhs.as_string () < rhs.as_string (); } }; + +template <> struct hash<Rust::Identifier> +{ + std::size_t operator() (const Rust::Identifier &k) const + { + using std::hash; + using std::size_t; + using std::string; + + return hash<string> () (k.as_string ()) ^ (hash<int> () (k.get_locus ())); + } +}; + } // namespace std #endif diff --git a/gcc/rust/ast/rust-builtin-ast-nodes.h b/gcc/rust/ast/rust-builtin-ast-nodes.h index 7ebd656..3684092 100644 --- a/gcc/rust/ast/rust-builtin-ast-nodes.h +++ b/gcc/rust/ast/rust-builtin-ast-nodes.h @@ -202,6 +202,8 @@ public: const FormatArguments &get_arguments () const { return arguments; } virtual location_t get_locus () const override; + Expr::Kind get_expr_kind () const override { return Expr::Kind::FormatArgs; } + private: location_t loc; // FIXME: This probably needs to be a separate type - it is one in rustc's diff --git a/gcc/rust/ast/rust-collect-lang-items.cc b/gcc/rust/ast/rust-collect-lang-items.cc new file mode 100644 index 0000000..cd6be7f --- /dev/null +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -0,0 +1,113 @@ +// Copyright (C) 2024 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-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" +#include "rust-hir-map.h" +#include "rust-item.h" + +namespace Rust { +namespace AST { + +template <typename T> +tl::optional<LangItem::Kind> +get_lang_item_attr (const T &maybe_lang_item) +{ + for (const auto &attr : maybe_lang_item.get_outer_attrs ()) + { + const auto &str_path = attr.get_path ().as_string (); + if (!Analysis::Attributes::is_known (str_path)) + { + rust_error_at (attr.get_locus (), "unknown attribute %qs", + str_path.c_str ()); + continue; + } + + bool is_lang_item = str_path == Values::Attributes::LANG + && attr.has_attr_input () + && attr.get_attr_input ().get_attr_input_type () + == AST::AttrInput::AttrInputType::LITERAL; + + if (is_lang_item) + { + auto &literal + = static_cast<AST::AttrInputLiteral &> (attr.get_attr_input ()); + const auto &lang_item_type_str = literal.get_literal ().as_string (); + + return LangItem::Parse (lang_item_type_str); + } + } + + return tl::nullopt; +} + +template <typename T> +void +CollectLangItems::maybe_add_lang_item (const T &item) +{ + if (auto lang_item = get_lang_item_attr (item)) + mappings.insert_lang_item_node (lang_item.value (), item.get_node_id ()); +} + +void +CollectLangItems::visit (AST::Trait &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::TraitItemType &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::Function &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::StructStruct &item) +{ + maybe_add_lang_item (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 new file mode 100644 index 0000000..ddb34a9 --- /dev/null +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -0,0 +1,61 @@ +// Copyright (C) 2024 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_COLLECT_LANG_ITEMS_H +#define RUST_COLLECT_LANG_ITEMS_H + +#include "rust-ast-visitor.h" +#include "rust-ast.h" +#include "rust-hir-map.h" +#include "rust-item.h" + +namespace Rust { +namespace AST { + +// This class collects lang items ahead of lowering, as they are now needed for +// some parts of name resolution +class CollectLangItems : public DefaultASTVisitor +{ +public: + CollectLangItems () : mappings (Analysis::Mappings::get ()){}; + + void go (AST::Crate &crate) { DefaultASTVisitor::visit (crate); } + + Analysis::Mappings &mappings; + + // We must implement visitors for all constructs that could be lang items. + // Lang items can be traits, but also enums, and even enum variants. + // + // https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs + + using DefaultASTVisitor::visit; + + void visit (AST::Trait &item) override; + 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); +}; + +} // namespace AST +} // namespace Rust + +#endif // ! RUST_COLLECT_LANG_ITEMS_H 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..ffc3470 --- /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 (tl::nullopt, 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 438d3d3..fdb6360 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -15,7 +15,7 @@ namespace AST { // Loop label expression AST node used with break and continue expressions // TODO: inline? -class LoopLabel /*: public Node*/ +class LoopLabel /*: public Visitable*/ { Lifetime label; // or type LIFETIME_OR_LABEL location_t locus; @@ -31,11 +31,6 @@ public: {} // Returns whether the LoopLabel is in an error state. - bool is_error () const { return label.is_error (); } - - // Creates an error state LoopLabel. - static LoopLabel error () { return LoopLabel (Lifetime::error ()); } - location_t get_locus () const { return locus; } Lifetime &get_lifetime () { return label; } @@ -117,6 +112,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Literal; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -365,6 +362,8 @@ public: { outer_attrs = std::move (new_attrs); } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Operator; } }; /* Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be @@ -403,6 +402,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 */ @@ -433,6 +434,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 */ @@ -464,6 +467,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 */ @@ -507,6 +515,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 */ @@ -595,6 +605,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 */ @@ -682,6 +697,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: @@ -770,6 +787,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 */ @@ -832,6 +851,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 */ @@ -910,6 +931,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 */ @@ -996,6 +1019,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 */ @@ -1090,6 +1118,8 @@ public: return expr_in_parens; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Grouped; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1319,6 +1349,8 @@ public: return internal_elements; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Array; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1424,6 +1456,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::ArrayIndex; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1520,6 +1554,8 @@ public: bool is_unit () const { return tuple_elems.size () == 0; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Tuple; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1607,6 +1643,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::TupleIndex; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -1650,6 +1688,8 @@ public: { outer_attrs = std::move (new_attrs); } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Struct; } }; // Actual AST node of the struct creator (with no fields). Not abstract! @@ -2123,6 +2163,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; } @@ -2131,6 +2173,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Call; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2234,6 +2278,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::MethodCall; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2319,6 +2365,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::FieldAccess; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -2454,6 +2502,8 @@ public: } bool get_has_move () const { return has_move; } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Closure; } }; // Represents a non-type-specified closure expression AST node @@ -2535,7 +2585,7 @@ class BlockExpr : public ExprWithBlock std::vector<Attribute> inner_attrs; std::vector<std::unique_ptr<Stmt> > statements; std::unique_ptr<Expr> expr; - LoopLabel label; + tl::optional<LoopLabel> label; location_t start_locus; location_t end_locus; bool marked_for_strip = false; @@ -2552,8 +2602,9 @@ public: BlockExpr (std::vector<std::unique_ptr<Stmt> > block_statements, std::unique_ptr<Expr> block_expr, std::vector<Attribute> inner_attribs, - std::vector<Attribute> outer_attribs, LoopLabel label, - location_t start_locus, location_t end_locus) + std::vector<Attribute> outer_attribs, + tl::optional<LoopLabel> label, location_t start_locus, + location_t end_locus) : outer_attrs (std::move (outer_attribs)), inner_attrs (std::move (inner_attribs)), statements (std::move (block_statements)), expr (std::move (block_expr)), @@ -2672,8 +2723,10 @@ public: outer_attrs = std::move (new_attrs); } - bool has_label () { return !label.is_error (); } - LoopLabel &get_label () { return label; } + bool has_label () { return label.has_value (); } + LoopLabel &get_label () { return label.value (); } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Block; } protected: /* Use covariance to implement clone function as returning this object rather @@ -2791,7 +2844,7 @@ protected: class ContinueExpr : public ExprWithoutBlock { std::vector<Attribute> outer_attrs; - Lifetime label; + tl::optional<Lifetime> label; location_t locus; // TODO: find another way to store this to save memory? @@ -2801,11 +2854,11 @@ public: std::string as_string () const override; // Returns true if the continue expr has a label. - bool has_label () const { return !label.is_error (); } + bool has_label () const { return label.has_value (); } // Constructor for a ContinueExpr with a label. - ContinueExpr (Lifetime label, std::vector<Attribute> outer_attribs, - location_t locus) + ContinueExpr (tl::optional<Lifetime> label, + std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), label (std::move (label)), locus (locus) {} @@ -2826,7 +2879,13 @@ public: outer_attrs = std::move (new_attrs); } - Lifetime &get_label () { return label; } + Lifetime &get_label_unchecked () { return label.value (); } + const Lifetime &get_label_unchecked () const { return label.value (); } + + tl::optional<Lifetime> &get_label () { return label; } + const tl::optional<Lifetime> &get_label () const { return label; } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Continue; } protected: /* Use covariance to implement clone function as returning this object rather @@ -2842,7 +2901,7 @@ protected: class BreakExpr : public ExprWithoutBlock { std::vector<Attribute> outer_attrs; - LoopLabel label; + tl::optional<LoopLabel> label; std::unique_ptr<Expr> break_expr; location_t locus; @@ -2853,14 +2912,15 @@ public: std::string as_string () const override; // Returns whether the break expression has a label or not. - bool has_label () const { return !label.is_error (); } + bool has_label () const { return label.has_value (); } /* Returns whether the break expression has an expression used in the break or * not. */ bool has_break_expr () const { return break_expr != nullptr; } // Constructor for a break expression - BreakExpr (LoopLabel break_label, std::unique_ptr<Expr> expr_in_break, + BreakExpr (tl::optional<LoopLabel> break_label, + std::unique_ptr<Expr> expr_in_break, std::vector<Attribute> outer_attribs, location_t locus) : outer_attrs (std::move (outer_attribs)), label (std::move (break_label)), break_expr (std::move (expr_in_break)), locus (locus) @@ -2922,7 +2982,13 @@ public: outer_attrs = std::move (new_attrs); } - LoopLabel &get_label () { return label; } + LoopLabel &get_label_unchecked () { return label.value (); } + const LoopLabel &get_label_unchecked () const { return label.value (); } + + tl::optional<LoopLabel> &get_label () { return label; } + const tl::optional<LoopLabel> &get_label () const { return label; } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Break; } protected: /* Use covariance to implement clone function as returning this object rather @@ -2938,6 +3004,10 @@ class RangeExpr : public ExprWithoutBlock { location_t locus; + // Some visitors still check for attributes on RangeExprs, and they will need + // to be supported in the future - so keep that for now + std::vector<Attribute> empty_attributes = {}; + protected: // outer attributes not allowed before range expressions RangeExpr (location_t locus) : locus (locus) {} @@ -2947,15 +3017,13 @@ public: std::vector<Attribute> &get_outer_attrs () override final { - // RangeExpr cannot have any outer attributes - rust_assert (false); + return empty_attributes; } // should never be called - error if called - void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override - { - rust_assert (false); - } + void set_outer_attrs (std::vector<Attribute> /* new_attrs */) override {} + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Range; } }; // Range from (inclusive) and to (exclusive) expression AST node object @@ -3404,6 +3472,8 @@ public: return *expr; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Box; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3491,6 +3561,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Return; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3573,6 +3645,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::UnsafeBlock; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3588,7 +3662,7 @@ class BaseLoopExpr : public ExprWithBlock protected: // protected to allow subclasses better use of them std::vector<Attribute> outer_attrs; - LoopLabel loop_label; + tl::optional<LoopLabel> loop_label; std::unique_ptr<BlockExpr> loop_block; private: @@ -3597,7 +3671,7 @@ private: protected: // Constructor for BaseLoopExpr BaseLoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : outer_attrs (std::move (outer_attribs)), @@ -3637,9 +3711,10 @@ protected: BaseLoopExpr &operator= (BaseLoopExpr &&other) = default; public: - bool has_loop_label () const { return !loop_label.is_error (); } + bool has_loop_label () const { return loop_label.has_value (); } - LoopLabel &get_loop_label () { return loop_label; } + LoopLabel &get_loop_label () { return loop_label.value (); } + const LoopLabel &get_loop_label () const { return loop_label.value (); } location_t get_locus () const override final { return locus; } @@ -3661,6 +3736,18 @@ public: { outer_attrs = std::move (new_attrs); } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::Loop; } + + enum class Kind + { + Loop, + While, + WhileLet, + For + }; + + virtual Kind get_loop_kind () const = 0; }; // 'Loop' expression (i.e. the infinite loop) AST node @@ -3671,7 +3758,7 @@ public: // Constructor for LoopExpr LoopExpr (std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label), std::move (outer_attribs)) @@ -3679,6 +3766,11 @@ public: void accept_vis (ASTVisitor &vis) override; + BaseLoopExpr::Kind get_loop_kind () const override + { + return BaseLoopExpr::Kind::Loop; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3699,7 +3791,7 @@ public: // Constructor for while loop with loop label WhileLoopExpr (std::unique_ptr<Expr> loop_condition, std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label), @@ -3737,6 +3829,11 @@ public: return *condition; } + BaseLoopExpr::Kind get_loop_kind () const override + { + return BaseLoopExpr::Kind::While; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3760,7 +3857,7 @@ public: WhileLetLoopExpr (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, std::unique_ptr<Expr> scrutinee, std::unique_ptr<BlockExpr> loop_block, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (loop_block), locus, std::move (loop_label), @@ -3820,6 +3917,11 @@ public: return match_arm_patterns; } + BaseLoopExpr::Kind get_loop_kind () const override + { + return BaseLoopExpr::Kind::WhileLet; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3842,7 +3944,7 @@ public: ForLoopExpr (std::unique_ptr<Pattern> loop_pattern, std::unique_ptr<Expr> iterator_expr, std::unique_ptr<BlockExpr> loop_body, location_t locus, - LoopLabel loop_label = LoopLabel::error (), + tl::optional<LoopLabel> loop_label = tl::nullopt, std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) : BaseLoopExpr (std::move (loop_body), locus, std::move (loop_label), std::move (outer_attribs)), @@ -3889,6 +3991,11 @@ public: return *pattern; } + BaseLoopExpr::Kind get_loop_kind () const override + { + return BaseLoopExpr::Kind::For; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4012,6 +4119,8 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::If; } + protected: // Base clone function but still concrete as concrete base class virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); } @@ -4206,6 +4315,8 @@ public: const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::IfLet; } + protected: /* Use covariance to implement clone function as returning this object rather * than base (or rather this or any derived object) */ @@ -4535,6 +4646,8 @@ public: const std::vector<MatchCase> &get_match_cases () const { return match_arms; } std::vector<MatchCase> &get_match_cases () { return match_arms; } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Match; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4614,6 +4727,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::Await; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4696,6 +4811,8 @@ public: outer_attrs = std::move (new_attrs); } + Expr::Kind get_expr_kind () const override { return Expr::Kind::AsyncBlock; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -4768,6 +4885,27 @@ struct InlineAsmRegOrRegClass location_t locus; }; +struct LlvmOperand +{ + std::string constraint; + std::unique_ptr<Expr> expr; + + LlvmOperand (std::string constraint, std::unique_ptr<Expr> &&expr) + : constraint (constraint), expr (std::move (expr)) + {} + + LlvmOperand (const LlvmOperand &other) + : constraint (other.constraint), expr (other.expr->clone_expr ()) + {} + LlvmOperand &operator= (const LlvmOperand &other) + { + constraint = other.constraint; + expr = other.expr->clone_expr (); + + return *this; + } +}; + class InlineAsmOperand { public: @@ -4810,14 +4948,14 @@ public: rust_assert (this->expr != nullptr); } - In (const struct In &other) + In (const In &other) { reg = other.reg; expr = other.expr->clone_expr (); } - In operator= (const struct In &other) + In operator= (const In &other) { reg = other.reg; expr = other.expr->clone_expr (); @@ -4843,14 +4981,14 @@ public: rust_assert (this->expr != nullptr); } - Out (const struct Out &other) + Out (const Out &other) { reg = other.reg; late = other.late; expr = other.expr->clone_expr (); } - Out operator= (const struct Out &other) + Out operator= (const Out &other) { reg = other.reg; late = other.late; @@ -4876,14 +5014,14 @@ public: rust_assert (this->expr != nullptr); } - InOut (const struct InOut &other) + InOut (const InOut &other) { reg = other.reg; late = other.late; expr = other.expr->clone_expr (); } - InOut operator= (const struct InOut &other) + InOut operator= (const InOut &other) { reg = other.reg; late = other.late; @@ -4913,7 +5051,7 @@ public: rust_assert (this->out_expr != nullptr); } - SplitInOut (const struct SplitInOut &other) + SplitInOut (const SplitInOut &other) { reg = other.reg; late = other.late; @@ -4921,7 +5059,7 @@ public: out_expr = other.out_expr->clone_expr (); } - SplitInOut operator= (const struct SplitInOut &other) + SplitInOut operator= (const SplitInOut &other) { reg = other.reg; late = other.late; @@ -4953,12 +5091,12 @@ public: { rust_assert (this->expr != nullptr); } - Sym (const struct Sym &other) + Sym (const Sym &other) { expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); } - Sym operator= (const struct Sym &other) + Sym operator= (const Sym &other) { expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); return *this; @@ -4981,12 +5119,12 @@ public: if (label_name.has_value ()) this->label_name = label_name.value (); } - Label (const struct Label &other) + Label (const Label &other) { expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); } - Label operator= (const struct Label &other) + Label operator= (const Label &other) { expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); return *this; @@ -5141,6 +5279,7 @@ struct TupleTemplateStr location_t loc; std::string symbol; + location_t get_locus () { return loc; } TupleTemplateStr (location_t loc, const std::string &symbol) : loc (loc), symbol (symbol) {} @@ -5209,6 +5348,79 @@ public: { return new InlineAsm (*this); } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; } +}; + +class LlvmInlineAsm : public ExprWithoutBlock +{ + // llvm_asm!("" : : "r"(&mut dummy) : "memory" : "volatile"); + // Asm, Outputs, Inputs, Clobbers, Options, + +public: + enum class Dialect + { + Att, + Intel, + }; + +private: + location_t locus; + std::vector<Attribute> outer_attrs; + std::vector<LlvmOperand> inputs; + std::vector<LlvmOperand> outputs; + std::vector<TupleTemplateStr> templates; + std::vector<TupleClobber> clobbers; + bool volatility; + bool align_stack; + Dialect dialect; + +public: + LlvmInlineAsm (location_t locus) : locus (locus) {} + + Dialect get_dialect () { return dialect; } + + location_t get_locus () const override { return locus; } + + void mark_for_strip () override {} + + bool is_marked_for_strip () const override { return false; } + + std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + + void accept_vis (ASTVisitor &vis) override; + + std::string as_string () const override { return "InlineAsm AST Node"; } + + void set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; } + + LlvmInlineAsm *clone_expr_without_block_impl () const override + { + return new LlvmInlineAsm (*this); + } + + std::vector<TupleTemplateStr> &get_templates () { return templates; } + + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::LlvmInlineAsm; + } + + void set_align_stack (bool align_stack) { this->align_stack = align_stack; } + bool is_stack_aligned () { return align_stack; } + + void set_volatile (bool volatility) { this->volatility = volatility; } + bool is_volatile () { return volatility; } + + void set_dialect (Dialect dialect) { this->dialect = dialect; } + + void set_inputs (std::vector<LlvmOperand> operands) { inputs = operands; } + void set_outputs (std::vector<LlvmOperand> operands) { outputs = operands; } + + std::vector<LlvmOperand> &get_inputs () { return inputs; } + std::vector<LlvmOperand> &get_outputs () { return outputs; } + + std::vector<TupleClobber> &get_clobbers () { return clobbers; } }; } // namespace AST diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index 2ae7c44..062f85d 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -434,13 +434,14 @@ class SelfParam : public Param bool has_ref; bool is_mut; // bool has_lifetime; // only possible if also ref - Lifetime lifetime; + tl::optional<Lifetime> lifetime; // bool has_type; // only possible if not ref std::unique_ptr<Type> type; // Unrestricted constructor used for error state - SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type) + SelfParam (tl::optional<Lifetime> lifetime, bool has_ref, bool is_mut, + Type *type) : Param ({}, UNDEF_LOCATION), has_ref (has_ref), is_mut (is_mut), lifetime (std::move (lifetime)), type (type) {} @@ -453,7 +454,7 @@ public: bool has_type () const { return type != nullptr; } // Returns whether the self-param has a valid lifetime. - bool has_lifetime () const { return !lifetime.is_error (); } + bool has_lifetime () const { return lifetime.has_value (); } // Returns whether the self-param is in an error state. bool is_error () const @@ -472,11 +473,11 @@ public: // Type-based self parameter (not ref, no lifetime) SelfParam (std::unique_ptr<Type> type, bool is_mut, location_t locus) : Param ({}, locus), has_ref (false), is_mut (is_mut), - lifetime (Lifetime::error ()), type (std::move (type)) + lifetime (tl::nullopt), type (std::move (type)) {} // Lifetime-based self parameter (is ref, no type) - SelfParam (Lifetime lifetime, bool is_mut, location_t locus) + SelfParam (tl::optional<Lifetime> lifetime, bool is_mut, location_t locus) : Param ({}, locus), has_ref (true), is_mut (is_mut), lifetime (std::move (lifetime)) {} @@ -522,8 +523,8 @@ public: bool get_has_ref () const { return has_ref; }; bool get_is_mut () const { return is_mut; } - Lifetime get_lifetime () const { return lifetime; } - Lifetime &get_lifetime () { return lifetime; } + Lifetime get_lifetime () const { return lifetime.value (); } + Lifetime &get_lifetime () { return lifetime.value (); } NodeId get_node_id () const { return node_id; } @@ -758,8 +759,6 @@ public: Identifier get_name () const { return module_name; } - AST::Kind get_ast_kind () const override { return AST::Kind::MODULE; } - private: Identifier module_name; location_t locus; @@ -899,6 +898,8 @@ public: void mark_for_strip () override { module_name = {""}; } bool is_marked_for_strip () const override { return module_name.empty (); } + Item::Kind get_item_kind () const override { return Item::Kind::Module; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -960,6 +961,8 @@ public: return referenced_crate.empty (); } + Item::Kind get_item_kind () const override { return Item::Kind::ExternCrate; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1301,6 +1304,11 @@ public: void mark_for_strip () override { use_tree = nullptr; } bool is_marked_for_strip () const override { return use_tree == nullptr; } + Item::Kind get_item_kind () const override + { + return Item::Kind::UseDeclaration; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1323,7 +1331,7 @@ class Function : public VisItem, public AssociatedItem, public ExternalItem WhereClause where_clause; tl::optional<std::unique_ptr<BlockExpr>> function_body; location_t locus; - bool is_default; + bool has_default; bool is_external_function; public: @@ -1348,6 +1356,8 @@ public: bool has_body () const { return function_body.has_value (); } + bool is_default () const { return has_default; } + // Mega-constructor with all possible fields Function (Identifier function_name, FunctionQualifiers qualifiers, std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -1355,7 +1365,7 @@ public: std::unique_ptr<Type> return_type, WhereClause where_clause, tl::optional<std::unique_ptr<BlockExpr>> function_body, Visibility vis, std::vector<Attribute> outer_attrs, - location_t locus, bool is_default = false, + location_t locus, bool has_default = false, bool is_external_function = false) : VisItem (std::move (vis), std::move (outer_attrs)), ExternalItem (Stmt::node_id), qualifiers (std::move (qualifiers)), @@ -1365,7 +1375,7 @@ public: return_type (std::move (return_type)), where_clause (std::move (where_clause)), function_body (std::move (function_body)), locus (locus), - is_default (is_default), is_external_function (is_external_function) + has_default (has_default), is_external_function (is_external_function) {} // TODO: add constructor with less fields @@ -1459,6 +1469,8 @@ public: // ExternalItem::node_id is same as Stmt::node_id NodeId get_node_id () const override { return Stmt::node_id; } + Item::Kind get_item_kind () const override { return Item::Kind::Function; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1590,6 +1602,8 @@ public: Identifier get_new_type_name () const { return new_type_name; } + Item::Kind get_item_kind () const override { return Item::Kind::TypeAlias; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1649,6 +1663,8 @@ public: Identifier get_identifier () const { return struct_name; } + Item::Kind get_item_kind () const override { return Item::Kind::Struct; } + protected: Struct (Identifier struct_name, std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -1994,6 +2010,41 @@ class EnumItem : public VisItem location_t locus; public: + enum class Kind + { + Identifier, + Tuple, + Struct, + + // FIXME: In the future, we'll need to remove this possibility as well as + // remove the EnumItemDiscriminant class. The feature for arbitrary + // discriminants on all kinds of variants has been stabilized, and a + // "discriminant" is no longer an enum item variant - it's simply an + // optional part of all variants. + // + // Per the reference: + // + // EnumItem : + // OuterAttribute* Visibility? + // IDENTIFIER ( EnumItemTuple | EnumItemStruct )? EnumItemDiscriminant? + // + // EnumItemTuple : + // ( TupleFields? ) + // + // EnumItemStruct : + // { StructFields? } + // + // EnumItemDiscriminant : + // = Expression + // + // So we instead need to remove the class, and add an optional expression to + // the base EnumItem class + // + // gccrs#3340 + + Discriminant, + }; + virtual ~EnumItem () {} EnumItem (Identifier variant_name, Visibility vis, @@ -2002,6 +2053,8 @@ public: variant_name (std::move (variant_name)), locus (locus) {} + virtual Kind get_enum_item_kind () const { return Kind::Identifier; } + // Unique pointer custom clone function std::unique_ptr<EnumItem> clone_enum_item () const { @@ -2021,6 +2074,8 @@ public: void mark_for_strip () override { variant_name = {""}; } bool is_marked_for_strip () const override { return variant_name.empty (); } + Item::Kind get_item_kind () const override { return Item::Kind::EnumItem; } + protected: EnumItem *clone_item_impl () const override { return new EnumItem (*this); } }; @@ -2043,6 +2098,11 @@ public: tuple_fields (std::move (tuple_fields)) {} + EnumItem::Kind get_enum_item_kind () const override + { + return EnumItem::Kind::Tuple; + } + std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; @@ -2080,6 +2140,11 @@ public: struct_fields (std::move (struct_fields)) {} + EnumItem::Kind get_enum_item_kind () const override + { + return EnumItem::Kind::Struct; + } + std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; @@ -2133,6 +2198,11 @@ public: EnumItemDiscriminant (EnumItemDiscriminant &&other) = default; EnumItemDiscriminant &operator= (EnumItemDiscriminant &&other) = default; + EnumItem::Kind get_enum_item_kind () const override + { + return EnumItem::Kind::Discriminant; + } + std::string as_string () const override; void accept_vis (ASTVisitor &vis) override; @@ -2269,6 +2339,8 @@ public: // TODO: is this better? Or is a "vis_block" better? WhereClause &get_where_clause () { return where_clause; } + Item::Kind get_item_kind () const override { return Item::Kind::Enum; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2368,6 +2440,8 @@ public: Identifier get_identifier () const { return union_name; } + Item::Kind get_item_kind () const override { return Item::Kind::Union; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2489,6 +2563,11 @@ public: std::string get_identifier () const { return identifier; } + Item::Kind get_item_kind () const override + { + return Item::Kind::ConstantItem; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2610,6 +2689,8 @@ public: Identifier get_identifier () const { return name; } + Item::Kind get_item_kind () const override { return Item::Kind::StaticItem; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -2831,6 +2912,7 @@ class Trait : public VisItem bool has_auto; Identifier name; std::vector<std::unique_ptr<GenericParam>> generic_params; + TypeParam self_param; std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; WhereClause where_clause; std::vector<Attribute> inner_attrs; @@ -2870,7 +2952,7 @@ public: std::vector<Attribute> inner_attrs, location_t locus) : VisItem (std::move (vis), std::move (outer_attrs)), has_unsafe (is_unsafe), has_auto (is_auto), name (std::move (name)), - generic_params (std::move (generic_params)), + generic_params (std::move (generic_params)), self_param ({"Self"}, locus), type_param_bounds (std::move (type_param_bounds)), where_clause (std::move (where_clause)), inner_attrs (std::move (inner_attrs)), @@ -2880,8 +2962,9 @@ public: // Copy constructor with vector clone Trait (Trait const &other) : VisItem (other), has_unsafe (other.has_unsafe), has_auto (other.has_auto), - name (other.name), where_clause (other.where_clause), - inner_attrs (other.inner_attrs), locus (other.locus) + name (other.name), self_param (other.self_param), + where_clause (other.where_clause), inner_attrs (other.inner_attrs), + locus (other.locus) { generic_params.reserve (other.generic_params.size ()); for (const auto &e : other.generic_params) @@ -2901,6 +2984,7 @@ public: { VisItem::operator= (other); name = other.name; + self_param = other.self_param; has_unsafe = other.has_unsafe; has_auto = other.has_auto; where_clause = other.where_clause; @@ -2968,19 +3052,9 @@ public: WhereClause &get_where_clause () { return where_clause; } - void insert_implict_self (std::unique_ptr<AST::GenericParam> &¶m) - { - std::vector<std::unique_ptr<GenericParam>> new_list; - new_list.reserve (generic_params.size () + 1); - - new_list.push_back (std::move (param)); - for (auto &p : generic_params) - { - new_list.push_back (std::move (p)); - } + AST::TypeParam &get_implicit_self () { return self_param; } - generic_params = std::move (new_list); - } + Item::Kind get_item_kind () const override { return Item::Kind::Trait; } protected: /* Use covariance to implement clone function as returning this object @@ -3054,6 +3128,8 @@ public: return trait_type; } + Item::Kind get_item_kind () const override { return Item::Kind::Impl; } + protected: // Mega-constructor Impl (std::vector<std::unique_ptr<GenericParam>> generic_params, @@ -3202,8 +3278,8 @@ public: : Impl (std::move (generic_params), std::move (trait_type), std::move (where_clause), std::move (vis), std::move (inner_attrs), std::move (outer_attrs), locus), - has_unsafe (is_unsafe), has_exclam (has_exclam), - trait_path (std::move (trait_path)), impl_items (std::move (impl_items)) + has_unsafe (is_unsafe), has_exclam (has_exclam), trait_path (trait_path), + impl_items (std::move (impl_items)) {} // Copy constructor with vector clone @@ -3251,11 +3327,7 @@ public: } // TODO: is this better? Or is a "vis_block" better? - TypePath &get_trait_path () - { - // TODO: assert that trait path is not empty? - return trait_path; - } + TypePath &get_trait_path () { return trait_path; } protected: /* Use covariance to implement clone function as returning this object @@ -3528,303 +3600,6 @@ protected: } }; -// A named function parameter used in external functions -class NamedFunctionParam -{ - // bool has_name; // otherwise is _ - std::string name; - - std::unique_ptr<Type> param_type; - - // seemingly new since writing this node - std::vector<Attribute> outer_attrs; - - NodeId node_id; - location_t locus; - bool variadic; - -public: - /* Returns whether the named function parameter has a name (i.e. name is not - * '_'). */ - bool has_name () const { return name != "_" && name != ""; } - - bool has_outer_attrs () const { return !outer_attrs.empty (); } - - // Returns whether the named function parameter is in an error state. - bool is_error () const - { - // also if identifier is "" but that is probably more costly to compute - return param_type == nullptr && !variadic; - } - - bool is_variadic () const { return variadic; } - - std::string get_name () const { return name; } - - location_t get_locus () { return locus; } - - // Creates an error state named function parameter. - static NamedFunctionParam create_error () - { - return NamedFunctionParam ("", nullptr, {}, UNDEF_LOCATION); - } - - NamedFunctionParam (std::string name, std::unique_ptr<Type> param_type, - std::vector<Attribute> outer_attrs, location_t locus) - : name (std::move (name)), param_type (std::move (param_type)), - outer_attrs (std::move (outer_attrs)), - node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus), - variadic (false) - {} - - NamedFunctionParam (std::string name, std::vector<Attribute> outer_attrs, - location_t locus) - : name (std::move (name)), param_type (nullptr), - outer_attrs (std::move (outer_attrs)), - node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus), - variadic (true) - {} - - NamedFunctionParam (std::vector<Attribute> outer_attrs, location_t locus) - : name (""), param_type (nullptr), outer_attrs (std::move (outer_attrs)), - node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus), - variadic (true) - {} - - // Copy constructor - NamedFunctionParam (NamedFunctionParam const &other) - : name (other.name), outer_attrs (other.outer_attrs), - variadic (other.variadic) - { - node_id = other.node_id; - // guard to prevent null dereference (only required if error state) - if (other.param_type != nullptr) - param_type = other.param_type->clone_type (); - else - param_type = nullptr; - } - - ~NamedFunctionParam () = default; - - // Overloaded assignment operator to clone - NamedFunctionParam &operator= (NamedFunctionParam const &other) - { - node_id = other.node_id; - name = other.name; - // has_name = other.has_name; - outer_attrs = other.outer_attrs; - - // guard to prevent null dereference (only required if error state) - if (other.param_type != nullptr) - param_type = other.param_type->clone_type (); - else - param_type = nullptr; - - return *this; - } - - // move constructors - NamedFunctionParam (NamedFunctionParam &&other) = default; - NamedFunctionParam &operator= (NamedFunctionParam &&other) = default; - - std::string as_string () const; - - // Based on idea that nane should never be empty. - void mark_for_strip () { param_type = nullptr; }; - bool is_marked_for_strip () const { return is_error (); }; - - // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } - - // TODO: is this better? Or is a "vis_block" better? - Type &get_type () - { - rust_assert (param_type != nullptr); - return *param_type; - } - - std::unique_ptr<Type> &get_type_ptr () - { - rust_assert (param_type != nullptr); - return param_type; - } - - NodeId get_node_id () const { return node_id; } -}; - -// A function item used in an extern block -class ExternalFunctionItem : public ExternalItem -{ - // bool has_outer_attrs; - std::vector<Attribute> outer_attrs; - - // bool has_visibility; - Visibility visibility; - - Identifier item_name; - location_t locus; - - // bool has_generics; - // Generics generic_params; - std::vector<std::unique_ptr<GenericParam>> generic_params; // inlined - - // bool has_return_type; - // FunctionReturnType return_type; - std::unique_ptr<Type> return_type; // inlined - - // bool has_where_clause; - WhereClause where_clause; - - std::vector<NamedFunctionParam> function_params; - -public: - // Returns whether item has generic parameters. - bool has_generics () const { return !generic_params.empty (); } - - // Returns whether item has a return type (otherwise void). - bool has_return_type () const { return return_type != nullptr; } - - // Returns whether item has a where clause. - bool has_where_clause () const { return !where_clause.is_empty (); } - - // Returns whether item has outer attributes. - bool has_outer_attrs () const { return !outer_attrs.empty (); } - - // Returns whether item has non-default visibility. - bool has_visibility () const { return !visibility.is_error (); } - - // Returns whether item has variadic parameters. - bool is_variadic () const - { - return function_params.size () != 0 - && function_params.back ().is_variadic (); - } - - location_t get_locus () const { return locus; } - - Visibility &get_visibility () { return visibility; } - const Visibility &get_visibility () const { return visibility; } - - ExternalFunctionItem ( - Identifier item_name, - std::vector<std::unique_ptr<GenericParam>> generic_params, - std::unique_ptr<Type> return_type, WhereClause where_clause, - std::vector<NamedFunctionParam> function_params, Visibility vis, - std::vector<Attribute> outer_attrs, location_t locus) - : ExternalItem (), outer_attrs (std::move (outer_attrs)), - visibility (std::move (vis)), item_name (std::move (item_name)), - locus (locus), generic_params (std::move (generic_params)), - return_type (std::move (return_type)), - where_clause (std::move (where_clause)), - function_params (std::move (function_params)) - { - // TODO: assert that if has variadic outer attrs, then has_variadics is - // true? - } - - // Copy constructor with clone - ExternalFunctionItem (ExternalFunctionItem const &other) - : ExternalItem (other.get_node_id ()), outer_attrs (other.outer_attrs), - visibility (other.visibility), item_name (other.item_name), - locus (other.locus), where_clause (other.where_clause), - function_params (other.function_params) - { - node_id = other.node_id; - // guard to prevent null pointer dereference - if (other.return_type != nullptr) - return_type = other.return_type->clone_type (); - - generic_params.reserve (other.generic_params.size ()); - for (const auto &e : other.generic_params) - generic_params.push_back (e->clone_generic_param ()); - } - - // Overloaded assignment operator with clone - ExternalFunctionItem &operator= (ExternalFunctionItem const &other) - { - outer_attrs = other.outer_attrs; - visibility = other.visibility; - item_name = other.item_name; - locus = other.locus; - where_clause = other.where_clause; - function_params = other.function_params; - node_id = other.node_id; - - // guard to prevent null pointer dereference - if (other.return_type != nullptr) - return_type = other.return_type->clone_type (); - else - return_type = nullptr; - - generic_params.reserve (other.generic_params.size ()); - for (const auto &e : other.generic_params) - generic_params.push_back (e->clone_generic_param ()); - - return *this; - } - - // move constructors - ExternalFunctionItem (ExternalFunctionItem &&other) = default; - ExternalFunctionItem &operator= (ExternalFunctionItem &&other) = default; - - std::string as_string () const override; - - void accept_vis (ASTVisitor &vis) override; - - // Based on idea that nane should never be empty. - void mark_for_strip () override { item_name = {""}; }; - bool is_marked_for_strip () const override { return item_name.empty (); }; - - // TODO: this mutable getter seems really dodgy. Think up better way. - std::vector<Attribute> &get_outer_attrs () { return outer_attrs; } - const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } - - std::vector<NamedFunctionParam> &get_function_params () - { - return function_params; - } - const std::vector<NamedFunctionParam> &get_function_params () const - { - return function_params; - } - - std::vector<std::unique_ptr<GenericParam>> &get_generic_params () - { - return generic_params; - } - const std::vector<std::unique_ptr<GenericParam>> &get_generic_params () const - { - return generic_params; - } - - // TODO: is this better? Or is a "vis_block" better? - WhereClause &get_where_clause () { return where_clause; } - - // TODO: is this better? Or is a "vis_block" better? - Type &get_return_type () - { - rust_assert (has_return_type ()); - return *return_type; - } - - std::unique_ptr<Type> &get_return_type_ptr () - { - rust_assert (has_return_type ()); - return return_type; - } - - Identifier get_identifier () const { return item_name; }; - -protected: - /* Use covariance to implement clone function as returning this object - * rather than base */ - ExternalFunctionItem *clone_external_item_impl () const override - { - return new ExternalFunctionItem (*this); - } -}; - // An extern block AST node class ExternBlock : public VisItem { @@ -3917,6 +3692,8 @@ public: const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } std::vector<Attribute> &get_inner_attrs () { return inner_attrs; } + Item::Kind get_item_kind () const override { return Item::Kind::ExternBlock; } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 76b3b2a..fc01e57 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -24,11 +24,11 @@ #include "rust-ast-fragment.h" #include "rust-location.h" #include "rust-item.h" -#include "rust-make-unique.h" #include "rust-macro-builtins.h" namespace Rust { namespace AST { + class MacroFragSpec { public: @@ -521,7 +521,7 @@ public: mbe (Identifier rule_name, DelimType delim_type, std::vector<MacroRule> rules, std::vector<Attribute> outer_attrs, location_t locus) { - return Rust::make_unique<MacroRulesDefinition> ( + return std::make_unique<MacroRulesDefinition> ( MacroRulesDefinition (rule_name, delim_type, rules, outer_attrs, locus, AST::MacroRulesDefinition::MacroKind::MBE, AST::Visibility::create_error ())); @@ -532,7 +532,7 @@ public: std::vector<Attribute> outer_attrs, location_t locus, Visibility vis) { - return Rust::make_unique<MacroRulesDefinition> (MacroRulesDefinition ( + return std::make_unique<MacroRulesDefinition> (MacroRulesDefinition ( rule_name, AST::DelimType::CURLY, rules, outer_attrs, locus, AST::MacroRulesDefinition::MacroKind::DeclMacro, vis)); } @@ -572,13 +572,13 @@ public: is_builtin_rule = true; } - AST::Kind get_ast_kind () const override + MacroKind get_kind () const { return kind; } + + Item::Kind get_item_kind () const override { - return AST::Kind::MACRO_RULES_DEFINITION; + return Item::Kind::MacroRulesDefinition; } - MacroKind get_kind () const { return kind; } - protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -610,11 +610,6 @@ public: std::string as_string () const override; - Pattern::Kind get_pattern_kind () override - { - return Pattern::Kind::MacroInvocation; - } - /** * The default constructor you should use. Whenever we parse a macro call, we * cannot possibly know whether or not this call refers to a builtin macro or @@ -677,11 +672,6 @@ public: return ExprWithoutBlock::get_node_id (); } - AST::Kind get_ast_kind () const override - { - return AST::Kind::MACRO_INVOCATION; - } - NodeId get_macro_node_id () const { return node_id; } MacroInvocData &get_invoc_data () { return invoc_data; } @@ -800,6 +790,21 @@ public: void add_semicolon () override { is_semi_coloned = true; } + Pattern::Kind get_pattern_kind () override + { + return Pattern::Kind::MacroInvocation; + } + + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::MacroInvocation; + } + + Item::Kind get_item_kind () const override + { + return Item::Kind::MacroInvocation; + } + protected: Item *clone_item_impl () const override { diff --git a/gcc/rust/ast/rust-path.cc b/gcc/rust/ast/rust-path.cc index 06c98cd..8e43ddf 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -119,7 +119,7 @@ ConstGenericParam::as_string () const str += "const " + name.as_string () + ": " + type->as_string (); if (has_default_value ()) - str += " = " + get_default_value ().as_string (); + str += " = " + get_default_value_unchecked ().as_string (); return str; } @@ -136,8 +136,11 @@ PathExprSegment::as_string () const } std::string -RegularPath::as_string () const +Path::as_string () const { + // FIXME: Impl for lang items + rust_assert (kind == Kind::Regular); + std::string str; for (const auto &segment : segments) @@ -149,16 +152,11 @@ RegularPath::as_string () const return str; } -std::string -LangItemPath::as_string () const -{ - // FIXME: Handle #[lang] paths - rust_unreachable (); -} - SimplePath -RegularPath::convert_to_simple_path (bool with_opening_scope_resolution) const +Path::convert_to_simple_path (bool with_opening_scope_resolution) const { + rust_assert (kind == Kind::Regular); + if (!has_segments ()) return SimplePath::create_empty (); @@ -192,18 +190,6 @@ RegularPath::convert_to_simple_path (bool with_opening_scope_resolution) const } void -RegularPath::accept_vis (ASTVisitor &vis) -{ - vis.visit (*this); -} - -void -LangItemPath::accept_vis (ASTVisitor &vis) -{ - vis.visit (*this); -} - -void PathInExpression::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -217,7 +203,7 @@ PathInExpression::as_string () const if (has_opening_scope_resolution) str = "::"; - return str + path->as_string (); + return str + Path::as_string (); } std::string @@ -317,7 +303,7 @@ TypePathFunction::as_string () const std::string QualifiedPathInExpression::as_string () const { - return path_type.as_string () + "::" + path->as_string (); + return path_type.as_string () + "::" + Path::as_string (); } std::string diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 98fde5a..a4ba93b 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -21,6 +21,7 @@ /* "Path" (identifier within namespaces, essentially) handling. Required include * for virtually all AST-related functionality. */ +#include "optional.h" #include "rust-ast.h" #include "rust-hir-map.h" #include "rust-mapping-common.h" @@ -55,10 +56,16 @@ public: location_t get_locus () const { return locus; } - bool is_super_segment () const { return as_string ().compare ("super") == 0; } - bool is_crate_segment () const { return as_string ().compare ("crate") == 0; } - bool is_lower_self () const { return as_string ().compare ("self") == 0; } - bool is_big_self () const { return as_string ().compare ("Self") == 0; } + bool is_super_path_seg () const + { + return as_string ().compare ("super") == 0; + } + bool is_crate_path_seg () const + { + return as_string ().compare ("crate") == 0; + } + bool is_lower_self_seg () const { return as_string ().compare ("self") == 0; } + bool is_big_self_seg () const { return as_string ().compare ("Self") == 0; } }; // A binding of an identifier to a type used in generic arguments in paths @@ -160,17 +167,11 @@ public: */ enum class Kind { - Error, Const, // A const value Type, // A type argument (not discernable during parsing) Either, // Either a type or a const value, cleared up during resolving }; - static GenericArg create_error () - { - return GenericArg (nullptr, nullptr, {""}, Kind::Error, UNDEF_LOCATION); - } - static GenericArg create_const (std::unique_ptr<Expr> expression) { auto locus = expression->get_locus (); @@ -215,8 +216,6 @@ public: GenericArg (GenericArg &&other) = default; GenericArg &operator= (GenericArg &&other) = default; - bool is_error () const { return kind == Kind::Error; } - Kind get_kind () const { return kind; } location_t get_locus () const { return locus; } @@ -232,8 +231,6 @@ public: break; case Kind::Either: break; - case Kind::Error: - rust_unreachable (); } } @@ -276,8 +273,6 @@ public: { switch (get_kind ()) { - case Kind::Error: - rust_unreachable (); case Kind::Either: return "Ambiguous: " + path.as_string (); case Kind::Const: @@ -348,15 +343,15 @@ class ConstGenericParam : public GenericParam /** * Default value for the const generic parameter */ - GenericArg default_value; + tl::optional<GenericArg> default_value; AST::AttrVec outer_attrs; location_t locus; public: ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type, - GenericArg default_value, AST::AttrVec outer_attrs, - location_t locus) + tl::optional<GenericArg> default_value, + AST::AttrVec outer_attrs, location_t locus) : name (name), type (std::move (type)), default_value (std::move (default_value)), outer_attrs (outer_attrs), locus (locus) @@ -369,7 +364,7 @@ public: {} bool has_type () const { return type != nullptr; } - bool has_default_value () const { return !default_value.is_error (); } + bool has_default_value () const { return default_value.has_value (); } const Identifier &get_name () const { return name; } @@ -382,18 +377,18 @@ public: return *type; } - GenericArg &get_default_value () + GenericArg &get_default_value_unchecked () { rust_assert (has_default_value ()); - return default_value; + return default_value.value (); } - const GenericArg &get_default_value () const + const GenericArg &get_default_value_unchecked () const { rust_assert (has_default_value ()); - return default_value; + return default_value.value (); } std::string as_string () const override; @@ -560,17 +555,17 @@ public: bool is_super_path_seg () const { - return !has_generic_args () && get_ident_segment ().is_super_segment (); + return !has_generic_args () && get_ident_segment ().is_super_path_seg (); } bool is_crate_path_seg () const { - return !has_generic_args () && get_ident_segment ().is_crate_segment (); + return !has_generic_args () && get_ident_segment ().is_crate_path_seg (); } bool is_lower_self_seg () const { - return !has_generic_args () && get_ident_segment ().is_lower_self (); + return !has_generic_args () && get_ident_segment ().is_lower_self_seg (); } }; @@ -585,104 +580,75 @@ public: Regular, }; - virtual Kind get_path_kind () const = 0; - - Pattern::Kind get_pattern_kind () override final - { - return Pattern::Kind::Path; - } - - location_t get_locus () const override final { return locus; } - NodeId get_node_id () const override final { return node_id; } - - std::unique_ptr<Path> clone_path () - { - return std::unique_ptr<Path> (clone_path_impl ()); - } - - Pattern *clone_pattern_impl () const override final - { - return clone_path_impl (); - } - -protected: - location_t locus; - NodeId node_id; - - Path (location_t locus, NodeId node_id) : locus (locus), node_id (node_id) {} - - virtual Path *clone_path_impl () const = 0; -}; - -class RegularPath : public Path -{ - std::vector<PathExprSegment> segments; - -public: - explicit RegularPath (std::vector<PathExprSegment> &&segments, - location_t locus, NodeId node_id) - : Path (locus, node_id), segments (std::move (segments)) + Path (std::vector<PathExprSegment> segments) + : segments (std::move (segments)), lang_item (tl::nullopt), + kind (Kind::Regular) {} - std::string as_string () const override; + Path (LangItem::Kind lang_item) + : segments ({}), lang_item (lang_item), kind (Kind::LangItem) + {} // Returns whether path has segments. - bool has_segments () const { return !segments.empty (); } - - std::vector<PathExprSegment> &get_segments () { return segments; } - - const std::vector<PathExprSegment> &get_segments () const { return segments; } - - /* Returns whether the path is a single segment (excluding qualified path - * initial as segment). */ - bool is_single_segment () const { return segments.size () == 1; } + bool has_segments () const + { + rust_assert (kind == Kind::Regular); + return !segments.empty (); + } /* Converts path segments to their equivalent SimplePath segments if * possible, and creates a SimplePath from them. */ SimplePath convert_to_simple_path (bool with_opening_scope_resolution) const; - Path::Kind get_path_kind () const override { return Path::Kind::Regular; } - - void accept_vis (ASTVisitor &vis) override; - - Path *clone_path_impl () const override + /* Returns whether the path is a single segment (excluding qualified path + * initial as segment). */ + bool is_single_segment () const { - return new RegularPath (std::vector<PathExprSegment> (segments), locus, - node_id); + rust_assert (kind == Kind::Regular); + return segments.size () == 1; } -}; - -class LangItemPath : public Path -{ - NodeId lang_item; - // TODO: Add LangItemKind or w/ever here as well - // TODO: This constructor is wrong - explicit LangItemPath (NodeId lang_item, location_t locus) - : Path (locus, lang_item), lang_item (lang_item) - {} + std::string as_string () const override; - Path::Kind get_path_kind () const override { return Path::Kind::LangItem; } + bool is_lang_item () const { return kind == Kind::LangItem; } - void accept_vis (ASTVisitor &vis) override; + // TODO: this seems kinda dodgy + std::vector<PathExprSegment> &get_segments () + { + rust_assert (kind == Kind::Regular); + return segments; + } + const std::vector<PathExprSegment> &get_segments () const + { + rust_assert (kind == Kind::Regular); + return segments; + } - Path *clone_path_impl () const override + LangItem::Kind get_lang_item () const { - return new LangItemPath (lang_item, locus); + rust_assert (kind == Kind::LangItem); + return *lang_item; } - std::string as_string () const override; + Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } + Path::Kind get_path_kind () { return kind; } + +protected: + std::vector<PathExprSegment> segments; + tl::optional<LangItem::Kind> lang_item; + + Path::Kind kind; }; /* AST node representing a path-in-expression pattern (path that allows * generic arguments) */ -class PathInExpression : public Pattern, public ExprWithoutBlock +class PathInExpression : public Path, public ExprWithoutBlock { std::vector<Attribute> outer_attrs; bool has_opening_scope_resolution; location_t locus; NodeId _node_id; - std::unique_ptr<Path> path; + bool marked_for_strip; public: @@ -692,61 +658,41 @@ public: PathInExpression (std::vector<PathExprSegment> path_segments, std::vector<Attribute> outer_attrs, location_t locus, bool has_opening_scope_resolution = false) - : outer_attrs (std::move (outer_attrs)), + : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)), has_opening_scope_resolution (has_opening_scope_resolution), locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()), - path (Rust::make_unique<RegularPath> (std::move (path_segments), locus, - _node_id)), marked_for_strip (false) {} - PathInExpression (const PathInExpression &other) - : outer_attrs (other.outer_attrs), - has_opening_scope_resolution (other.has_opening_scope_resolution), - locus (other.locus), _node_id (other._node_id), - path (other.path->clone_path ()), - marked_for_strip (other.marked_for_strip) + PathInExpression (LangItem::Kind lang_item, + std::vector<Attribute> outer_attrs, location_t locus) + : Path (lang_item), outer_attrs (std::move (outer_attrs)), + has_opening_scope_resolution (false), locus (locus), + _node_id (Analysis::Mappings::get ().get_next_node_id ()), + marked_for_strip (false) {} - PathInExpression &operator= (const PathInExpression &other) - { - outer_attrs = other.outer_attrs; - has_opening_scope_resolution = other.has_opening_scope_resolution; - locus = other.locus; - _node_id = other._node_id; - path = other.path->clone_path (); - marked_for_strip = other.marked_for_strip; - - return *this; - } - // Creates an error state path in expression. static PathInExpression create_error () { - return PathInExpression ({}, {}, UNDEF_LOCATION); + return PathInExpression (std::vector<PathExprSegment> (), {}, + UNDEF_LOCATION); } // Returns whether path in expression is in an error state. - bool is_error () const - { - // FIXME: Cleanup - if (path->get_path_kind () == Path::Kind::Regular) - return !static_cast<RegularPath &> (*path).has_segments (); - - return false; - } + bool is_error () const { return !has_segments (); } /* Converts PathInExpression to SimplePath if possible (i.e. no generic * arguments). Otherwise returns an empty SimplePath. */ SimplePath as_simple_path () const { - // FIXME: Cleanup - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).convert_to_simple_path ( - has_opening_scope_resolution); - else - // FIXME: lang item to simple path? - rust_unreachable (); + /* delegate to parent class as can't access segments. however, + * QualifiedPathInExpression conversion to simple path wouldn't make + * sense, so the method in the parent class should be protected, not + * public. Have to pass in opening scope resolution as parent class has no + * access to it. + */ + return convert_to_simple_path (has_opening_scope_resolution); } location_t get_locus () const override final { return locus; } @@ -771,63 +717,18 @@ public: outer_attrs = std::move (new_attrs); } - NodeId get_pattern_node_id () const { return get_node_id (); } - - PathExprSegment &get_final_segment () - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments ().back (); - - // lang item segment? - rust_unreachable (); - } - + PathExprSegment &get_final_segment () { return get_segments ().back (); } const PathExprSegment &get_final_segment () const { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments ().back (); - - // lang item segment? - rust_unreachable (); + return get_segments ().back (); } - const std::vector<PathExprSegment> &get_segments () const + Expr::Kind get_expr_kind () const override { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments (); - - rust_unreachable (); + return Expr::Kind::PathInExpression; } - std::vector<PathExprSegment> &get_segments () - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments (); - - rust_unreachable (); - } - - bool is_single_segment () const - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments ().size () == 1; - - return false; - } - - Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } - protected: - PathInExpression (std::vector<Attribute> &&outer_attrs, - bool has_opening_scope_resolution, location_t locus, - NodeId node_id, std::unique_ptr<Path> &&path, - bool marked_for_strip) - : outer_attrs (std::move (outer_attrs)), - has_opening_scope_resolution (has_opening_scope_resolution), - locus (locus), _node_id (node_id), path (std::move (path)), - marked_for_strip (marked_for_strip) - {} - /* Use covariance to implement clone function as returning this object * rather than base */ PathInExpression *clone_pattern_impl () const final override @@ -861,7 +762,8 @@ public: }; private: - PathIdentSegment ident_segment; + tl::optional<LangItem::Kind> lang_item; + tl::optional<PathIdentSegment> ident_segment; location_t locus; protected: @@ -891,21 +793,30 @@ public: TypePathSegment (PathIdentSegment ident_segment, bool has_separating_scope_resolution, location_t locus) - : ident_segment (std::move (ident_segment)), locus (locus), + : lang_item (tl::nullopt), ident_segment (std::move (ident_segment)), + locus (locus), has_separating_scope_resolution (has_separating_scope_resolution), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + TypePathSegment (LangItem::Kind lang_item, location_t locus) + : lang_item (lang_item), ident_segment (tl::nullopt), locus (locus), + has_separating_scope_resolution (false), + node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} + TypePathSegment (std::string segment_name, bool has_separating_scope_resolution, location_t locus) - : ident_segment (PathIdentSegment (std::move (segment_name), locus)), + : lang_item (tl::nullopt), + ident_segment (PathIdentSegment (std::move (segment_name), locus)), locus (locus), has_separating_scope_resolution (has_separating_scope_resolution), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} TypePathSegment (TypePathSegment const &other) - : ident_segment (other.ident_segment), locus (other.locus), + : lang_item (other.lang_item), ident_segment (other.ident_segment), + locus (other.locus), has_separating_scope_resolution (other.has_separating_scope_resolution), node_id (other.node_id) {} @@ -913,6 +824,7 @@ public: TypePathSegment &operator= (TypePathSegment const &other) { ident_segment = other.ident_segment; + lang_item = other.lang_item; locus = other.locus; has_separating_scope_resolution = other.has_separating_scope_resolution; node_id = other.node_id; @@ -923,16 +835,28 @@ public: TypePathSegment (TypePathSegment &&other) = default; TypePathSegment &operator= (TypePathSegment &&other) = default; - virtual std::string as_string () const { return ident_segment.as_string (); } + virtual std::string as_string () const + { + if (lang_item.has_value ()) + return LangItem::PrettyString (*lang_item); + + return ident_segment->as_string (); + } /* Returns whether the type path segment is in an error state. May be * virtual in future. */ - bool is_error () const { return ident_segment.is_error (); } + bool is_error () const + { + rust_assert (ident_segment); + return ident_segment->is_error (); + } /* Returns whether segment is identifier only (as opposed to generic args or * function). Overridden in derived classes with other segments. */ virtual bool is_ident_only () const { return true; } + bool is_lang_item () const { return lang_item.has_value (); } + location_t get_locus () const { return locus; } // not pure virtual as class not abstract @@ -943,23 +867,41 @@ public: return has_separating_scope_resolution; } - PathIdentSegment &get_ident_segment () { return ident_segment; }; - const PathIdentSegment &get_ident_segment () const { return ident_segment; }; + PathIdentSegment &get_ident_segment () + { + rust_assert (!is_lang_item ()); + return *ident_segment; + }; + + const PathIdentSegment &get_ident_segment () const + { + rust_assert (!is_lang_item ()); + return *ident_segment; + }; + + LangItem::Kind get_lang_item () const + { + rust_assert (is_lang_item ()); + return *lang_item; + } NodeId get_node_id () const { return node_id; } bool is_crate_path_seg () const { - return get_ident_segment ().is_crate_segment (); + return get_ident_segment ().is_crate_path_seg (); } bool is_super_path_seg () const { - return get_ident_segment ().is_super_segment (); + return get_ident_segment ().is_super_path_seg (); + } + bool is_big_self_seg () const + { + return get_ident_segment ().is_big_self_seg (); } - bool is_big_self_seg () const { return get_ident_segment ().is_big_self (); } bool is_lower_self_seg () const { - return get_ident_segment ().is_lower_self (); + return get_ident_segment ().is_lower_self_seg (); } }; @@ -984,6 +926,12 @@ public: generic_args (std::move (generic_args)) {} + TypePathSegmentGeneric (LangItem::Kind lang_item, GenericArgs generic_args, + location_t locus) + : TypePathSegment (lang_item, locus), + generic_args (std::move (generic_args)) + {} + // Constructor from segment name and all args TypePathSegmentGeneric (std::string segment_name, bool has_separating_scope_resolution, @@ -1041,7 +989,7 @@ private: /*bool has_inputs; TypePathFnInputs inputs;*/ // inlined from TypePathFnInputs - std::vector<std::unique_ptr<Type> > inputs; + std::vector<std::unique_ptr<Type>> inputs; // bool has_type; std::unique_ptr<Type> return_type; @@ -1074,8 +1022,8 @@ public: } // Constructor - TypePathFunction (std::vector<std::unique_ptr<Type> > inputs, - location_t locus, std::unique_ptr<Type> type = nullptr) + TypePathFunction (std::vector<std::unique_ptr<Type>> inputs, location_t locus, + std::unique_ptr<Type> type = nullptr) : inputs (std::move (inputs)), return_type (std::move (type)), is_invalid (false), locus (locus) {} @@ -1120,11 +1068,11 @@ public: std::string as_string () const; // TODO: this mutable getter seems really dodgy. Think up better way. - const std::vector<std::unique_ptr<Type> > &get_params () const + const std::vector<std::unique_ptr<Type>> &get_params () const { return inputs; } - std::vector<std::unique_ptr<Type> > &get_params () { return inputs; } + std::vector<std::unique_ptr<Type>> &get_params () { return inputs; } // TODO: is this better? Or is a "vis_pattern" better? Type &get_return_type () @@ -1188,11 +1136,10 @@ public: } }; -// Path used inside types class TypePath : public TypeNoBounds { bool has_opening_scope_resolution; - std::vector<std::unique_ptr<TypePathSegment> > segments; + std::vector<std::unique_ptr<TypePathSegment>> segments; location_t locus; protected: @@ -1217,12 +1164,20 @@ public: // Creates an error state TypePath. static TypePath create_error () { - return TypePath (std::vector<std::unique_ptr<TypePathSegment> > (), + return TypePath (std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION); } // Constructor - TypePath (std::vector<std::unique_ptr<TypePathSegment> > segments, + TypePath (std::vector<std::unique_ptr<TypePathSegment>> segments, + location_t locus, bool has_opening_scope_resolution = false) + : TypeNoBounds (), + has_opening_scope_resolution (has_opening_scope_resolution), + segments (std::move (segments)), locus (locus) + {} + + TypePath (LangItem::Kind lang_item, + std::vector<std::unique_ptr<TypePathSegment>> segments, location_t locus, bool has_opening_scope_resolution = false) : TypeNoBounds (), has_opening_scope_resolution (has_opening_scope_resolution), @@ -1268,15 +1223,19 @@ public: TraitBound *to_trait_bound (bool in_parens) const override; location_t get_locus () const override final { return locus; } + NodeId get_node_id () const { return node_id; } + + void mark_for_strip () override {} + bool is_marked_for_strip () const override { return false; } void accept_vis (ASTVisitor &vis) override; // TODO: this seems kinda dodgy - std::vector<std::unique_ptr<TypePathSegment> > &get_segments () + std::vector<std::unique_ptr<TypePathSegment>> &get_segments () { return segments; } - const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const + const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const { return segments; } @@ -1297,9 +1256,8 @@ public: QualifiedPathType (std::unique_ptr<Type> invoke_on_type, location_t locus = UNDEF_LOCATION, TypePath trait_path = TypePath::create_error ()) - : type_to_invoke_on (std::move (invoke_on_type)), - trait_path (std::move (trait_path)), locus (locus), - node_id (Analysis::Mappings::get ().get_next_node_id ()) + : type_to_invoke_on (std::move (invoke_on_type)), trait_path (trait_path), + locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Copy constructor uses custom deep copy for Type to preserve polymorphism @@ -1376,12 +1334,12 @@ public: /* AST node representing a qualified path-in-expression pattern (path that * allows specifying trait functions) */ -class QualifiedPathInExpression : public Pattern, public ExprWithoutBlock +class QualifiedPathInExpression : public Path, public ExprWithoutBlock { std::vector<Attribute> outer_attrs; QualifiedPathType path_type; - - std::unique_ptr<Path> path; + location_t locus; + NodeId _node_id; public: std::string as_string () const override; @@ -1390,16 +1348,9 @@ public: std::vector<PathExprSegment> path_segments, std::vector<Attribute> outer_attrs, location_t locus) - : outer_attrs (std::move (outer_attrs)), - path_type (std::move (qual_path_type)), - path (Rust::make_unique<RegularPath> ( - std::move (path_segments), locus, - Analysis::Mappings::get ().get_next_node_id ())) - {} - - QualifiedPathInExpression (const QualifiedPathInExpression &other) - : outer_attrs (other.outer_attrs), path_type (other.path_type), - path (other.path->clone_path ()) + : Path (std::move (path_segments)), outer_attrs (std::move (outer_attrs)), + path_type (std::move (qual_path_type)), locus (locus), + _node_id (Analysis::Mappings::get ().get_next_node_id ()) {} /* TODO: maybe make a shortcut constructor that has QualifiedPathType @@ -1415,9 +1366,7 @@ public: {}, UNDEF_LOCATION); } - Pattern::Kind get_pattern_kind () override { return Pattern::Kind::Path; } - - location_t get_locus () const override final { return path->get_locus (); } + location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; @@ -1443,30 +1392,11 @@ public: outer_attrs = std::move (new_attrs); } - NodeId get_node_id () const override { return path->get_node_id (); } - - const std::vector<PathExprSegment> &get_segments () const - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments (); - - rust_unreachable (); - } - - std::vector<PathExprSegment> &get_segments () - { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments (); - - rust_unreachable (); - } + NodeId get_node_id () const override { return _node_id; } - bool is_single_segment () const + Expr::Kind get_expr_kind () const override { - if (path->get_path_kind () == Path::Kind::Regular) - return static_cast<RegularPath &> (*path).get_segments ().size () == 1; - - return false; + return Expr::Kind::QualifiedPathInExpression; } protected: @@ -1498,7 +1428,7 @@ class QualifiedPathInType : public TypeNoBounds { QualifiedPathType path_type; std::unique_ptr<TypePathSegment> associated_segment; - std::vector<std::unique_ptr<TypePathSegment> > segments; + std::vector<std::unique_ptr<TypePathSegment>> segments; location_t locus; protected: @@ -1513,7 +1443,7 @@ public: QualifiedPathInType ( QualifiedPathType qual_path_type, std::unique_ptr<TypePathSegment> associated_segment, - std::vector<std::unique_ptr<TypePathSegment> > path_segments, + std::vector<std::unique_ptr<TypePathSegment>> path_segments, location_t locus) : path_type (std::move (qual_path_type)), associated_segment (std::move (associated_segment)), @@ -1560,7 +1490,7 @@ public: { return QualifiedPathInType ( QualifiedPathType::create_error (), nullptr, - std::vector<std::unique_ptr<TypePathSegment> > (), UNDEF_LOCATION); + std::vector<std::unique_ptr<TypePathSegment>> (), UNDEF_LOCATION); } std::string as_string () const override; @@ -1580,11 +1510,11 @@ public: } // TODO: this seems kinda dodgy - std::vector<std::unique_ptr<TypePathSegment> > &get_segments () + std::vector<std::unique_ptr<TypePathSegment>> &get_segments () { return segments; } - const std::vector<std::unique_ptr<TypePathSegment> > &get_segments () const + const std::vector<std::unique_ptr<TypePathSegment>> &get_segments () const { return segments; } 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 e8aec34..f843a79 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -19,10 +19,11 @@ #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" -#include <memory> +#include "rust-system.h" namespace Rust { namespace AST { @@ -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); diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 20e0232..1bb521d 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -542,7 +542,7 @@ protected: class ReferenceType : public TypeNoBounds { // bool has_lifetime; // TODO: handle in lifetime or something? - Lifetime lifetime; + tl::optional<Lifetime> lifetime; bool has_mut; std::unique_ptr<TypeNoBounds> type; @@ -553,11 +553,12 @@ public: bool is_mut () const { return has_mut; } // Returns whether the reference has a lifetime. - bool has_lifetime () const { return !lifetime.is_error (); } + bool has_lifetime () const { return lifetime.has_value (); } // Constructor ReferenceType (bool is_mut, std::unique_ptr<TypeNoBounds> type_no_bounds, - location_t locus, Lifetime lifetime = Lifetime::elided ()) + location_t locus, + tl::optional<Lifetime> lifetime = Lifetime::elided ()) : lifetime (std::move (lifetime)), has_mut (is_mut), type (std::move (type_no_bounds)), locus (locus) {} @@ -598,7 +599,8 @@ public: bool get_has_mut () const { return has_mut; } - Lifetime &get_lifetime () { return lifetime; } + Lifetime &get_lifetime () { return lifetime.value (); } + const Lifetime &get_lifetime () const { return lifetime.value (); } TypeNoBounds &get_base_type () { return *type; } |