diff options
Diffstat (limited to 'gcc/rust/ast')
32 files changed, 4364 insertions, 899 deletions
diff --git a/gcc/rust/ast/rust-ast-builder-type.cc b/gcc/rust/ast/rust-ast-builder-type.cc new file mode 100644 index 0000000..13126b4 --- /dev/null +++ b/gcc/rust/ast/rust-ast-builder-type.cc @@ -0,0 +1,163 @@ +// Copyright (C) 2020-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-ast-builder-type.h" +#include "rust-ast-builder.h" +#include "rust-ast-full.h" +#include "rust-common.h" + +namespace Rust { +namespace AST { + +ASTTypeBuilder::ASTTypeBuilder () : translated (nullptr) {} + +Type * +ASTTypeBuilder::build (Type &type) +{ + ASTTypeBuilder builder; + type.accept_vis (builder); + rust_assert (builder.translated != nullptr); + return builder.translated; +} + +void +ASTTypeBuilder::visit (BareFunctionType &fntype) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (TupleType &tuple) +{ + std::vector<std::unique_ptr<Type> > elems; + for (auto &elem : tuple.get_elems ()) + { + Type *t = ASTTypeBuilder::build (*elem.get ()); + std::unique_ptr<Type> ty (t); + elems.push_back (std::move (ty)); + } + translated = new TupleType (std::move (elems), tuple.get_locus ()); +} + +void +ASTTypeBuilder::visit (TypePath &path) +{ + std::vector<std::unique_ptr<TypePathSegment> > segments; + for (auto &seg : path.get_segments ()) + { + switch (seg->get_type ()) + { + case TypePathSegment::REG: { + const TypePathSegment &segment + = (const TypePathSegment &) (*seg.get ()); + TypePathSegment *s + = new TypePathSegment (segment.get_ident_segment (), + segment.get_separating_scope_resolution (), + segment.get_locus ()); + std::unique_ptr<TypePathSegment> sg (s); + segments.push_back (std::move (sg)); + } + break; + + case TypePathSegment::GENERIC: { + TypePathSegmentGeneric &generic + = (TypePathSegmentGeneric &) (*seg.get ()); + + GenericArgs args + = Builder::new_generic_args (generic.get_generic_args ()); + TypePathSegmentGeneric *s + = new TypePathSegmentGeneric (generic.get_ident_segment (), false, + std::move (args), + generic.get_locus ()); + std::unique_ptr<TypePathSegment> sg (s); + segments.push_back (std::move (sg)); + } + break; + + case TypePathSegment::FUNCTION: { + rust_unreachable (); + // TODO + // const TypePathSegmentFunction &fn + // = (const TypePathSegmentFunction &) (*seg.get ()); + } + break; + } + } + + translated = new TypePath (std::move (segments), path.get_locus (), + path.has_opening_scope_resolution_op ()); +} + +void +ASTTypeBuilder::visit (QualifiedPathInType &path) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (ArrayType &type) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (ReferenceType &type) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (RawPointerType &type) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (SliceType &type) +{ + Type *t = ASTTypeBuilder::build (type.get_elem_type ()); + std::unique_ptr<Type> ty (t); + translated = new SliceType (std::move (ty), type.get_locus ()); +} + +void +ASTTypeBuilder::visit (InferredType &type) +{ + translated = new InferredType (type.get_locus ()); +} + +void +ASTTypeBuilder::visit (NeverType &type) +{ + translated = new NeverType (type.get_locus ()); +} + +void +ASTTypeBuilder::visit (TraitObjectTypeOneBound &type) +{ + /* TODO */ +} + +void +ASTTypeBuilder::visit (TraitObjectType &type) +{ + /* TODO */ +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-builder-type.h b/gcc/rust/ast/rust-ast-builder-type.h new file mode 100644 index 0000000..b67ae3b --- /dev/null +++ b/gcc/rust/ast/rust-ast-builder-type.h @@ -0,0 +1,57 @@ +// Copyright (C) 2020-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_AST_BUILDER_TYPE +#define RUST_AST_BUILDER_TYPE + +#include "rust-ast-visitor.h" + +namespace Rust { +namespace AST { + +class ASTTypeBuilder : public DefaultASTVisitor +{ +protected: + using DefaultASTVisitor::visit; + +public: + static Type *build (Type &type); + + void visit (BareFunctionType &fntype) override; + void visit (TupleType &tuple) override; + void visit (TypePath &path) override; + void visit (QualifiedPathInType &path) override; + void visit (ArrayType &type) override; + void visit (ReferenceType &type) override; + void visit (RawPointerType &type) override; + void visit (SliceType &type) override; + void visit (InferredType &type) override; + void visit (NeverType &type) override; + void visit (TraitObjectTypeOneBound &type) override; + void visit (TraitObjectType &type) override; + +private: + ASTTypeBuilder (); + + Type *translated; +}; + +} // namespace AST +} // namespace Rust + +#endif // RUST_AST_BUILDER_TYPE diff --git a/gcc/rust/ast/rust-ast-builder.cc b/gcc/rust/ast/rust-ast-builder.cc index 1138d3d..e4c03e5 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 "rust-ast-full-decls.h" -#include "rust-ast-full.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 { @@ -82,6 +182,28 @@ Builder::type_path_segment (std::string seg) const new TypePathSegment (seg, false, loc)); } +std::unique_ptr<TypePathSegment> +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 { @@ -91,39 +213,156 @@ Builder::single_type_path (std::string type) const return std::unique_ptr<Type> (new TypePath (std::move (segments), loc)); } +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 (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> Builder::ref (std::unique_ptr<Expr> &&of, bool mut) const { + auto mutability = mut ? Mutability::Mut : Mutability::Imm; return std::unique_ptr<Expr> ( - new BorrowExpr (std::move (of), mut, /* is double */ false, {}, loc)); + new BorrowExpr (std::move (of), mutability, + /* raw */ false, /* is double */ false, {}, loc)); } std::unique_ptr<Expr> @@ -133,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> ( @@ -144,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> @@ -165,11 +442,280 @@ Builder::field_access (std::unique_ptr<Expr> &&instance, new FieldAccessExpr (std::move (instance), field, {}, loc)); } +std::unique_ptr<StructPatternField> +Builder::struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr<Pattern> &&pattern) +{ + return std::make_unique<StructPatternFieldIdentPat> ( + field_name, std::move (pattern), std::vector<Attribute> (), loc); +} + std::unique_ptr<Pattern> 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) +{ + Type *t = ASTTypeBuilder::build (type); + return std::unique_ptr<Type> (t); +} + +std::unique_ptr<GenericParam> +Builder::new_lifetime_param (LifetimeParam ¶m) +{ + Lifetime l = new_lifetime (param.get_lifetime ()); + std::vector<Lifetime> lifetime_bounds; + for (auto b : param.get_lifetime_bounds ()) + { + Lifetime bl = new_lifetime (b); + lifetime_bounds.push_back (bl); + } + + auto p = new LifetimeParam (l, std::move (lifetime_bounds), + param.get_outer_attrs (), param.get_locus ()); + return std::unique_ptr<GenericParam> (p); +} + +std::unique_ptr<GenericParam> +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 (); + Identifier type_representation = param.get_type_representation (); + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; + std::unique_ptr<Type> type = nullptr; + + 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 ()) + { + case TypeParamBound::TypeParamBoundType::TRAIT: { + const TraitBound &tb = (const TraitBound &) *b.get (); + const TypePath &path = tb.get_type_path (); + + std::vector<LifetimeParam> for_lifetimes; + for (const auto &lifetime : tb.get_for_lifetimes ()) + { + std::vector<Lifetime> lifetime_bounds; + for (const auto &b : lifetime.get_lifetime_bounds ()) + { + Lifetime bl = new_lifetime (b); + lifetime_bounds.push_back (std::move (bl)); + } + + Lifetime nl = new_lifetime (lifetime.get_lifetime ()); + LifetimeParam p (std::move (nl), std::move (lifetime_bounds), + {}, lifetime.get_locus ()); + for_lifetimes.push_back (std::move (p)); + } + + std::vector<std::unique_ptr<TypePathSegment>> segments; + for (auto &seg : path.get_segments ()) + { + switch (seg->get_type ()) + { + case TypePathSegment::REG: { + const TypePathSegment &segment + = (const TypePathSegment &) (*seg.get ()); + TypePathSegment *s = new TypePathSegment ( + segment.get_ident_segment (), + segment.get_separating_scope_resolution (), + segment.get_locus ()); + std::unique_ptr<TypePathSegment> sg (s); + segments.push_back (std::move (sg)); + } + break; + + case TypePathSegment::GENERIC: { + TypePathSegmentGeneric &generic + = (TypePathSegmentGeneric &) (*seg.get ()); + + GenericArgs args + = new_generic_args (generic.get_generic_args ()); + TypePathSegmentGeneric *s = new TypePathSegmentGeneric ( + generic.get_ident_segment (), false, std::move (args), + generic.get_locus ()); + std::unique_ptr<TypePathSegment> sg (s); + segments.push_back (std::move (sg)); + } + break; + + case TypePathSegment::FUNCTION: { + rust_unreachable (); + // TODO + // const TypePathSegmentFunction &fn + // = (const TypePathSegmentFunction &) (*seg.get ()); + } + break; + } + } + + TypePath p (std::move (segments), path.get_locus (), + path.has_opening_scope_resolution_op ()); + + TraitBound *b = new TraitBound (std::move (p), tb.get_locus (), + tb.is_in_parens (), + tb.has_opening_question_mark (), + std::move (for_lifetimes)); + std::unique_ptr<TypeParamBound> bound (b); + type_param_bounds.push_back (std::move (bound)); + } + break; + + case TypeParamBound::TypeParamBoundType::LIFETIME: { + const Lifetime &l = (const Lifetime &) *b.get (); + + auto bl = new Lifetime (l.get_lifetime_type (), + l.get_lifetime_name (), l.get_locus ()); + std::unique_ptr<TypeParamBound> bound (bl); + type_param_bounds.push_back (std::move (bound)); + } + break; + } + } + + auto type_param + = new TypeParam (type_representation, locus, std::move (type_param_bounds), + std::move (type), std::move (outer_attrs)); + + return std::unique_ptr<GenericParam> (type_param); +} + +Lifetime +Builder::new_lifetime (const Lifetime &lifetime) +{ + return Lifetime (lifetime.get_lifetime_type (), lifetime.get_lifetime_name (), + lifetime.get_locus ()); +} + +GenericArgs +Builder::new_generic_args (GenericArgs &args) +{ + std::vector<Lifetime> lifetime_args; + std::vector<GenericArg> generic_args; + std::vector<GenericArgsBinding> binding_args; + location_t locus = args.get_locus (); + + for (const auto &lifetime : args.get_lifetime_args ()) + { + Lifetime l = new_lifetime (lifetime); + lifetime_args.push_back (std::move (l)); + } + + for (auto &binding : args.get_binding_args ()) + { + Type &t = *binding.get_type_ptr ().get (); + std::unique_ptr<Type> ty = new_type (t); + GenericArgsBinding b (binding.get_identifier (), std::move (ty), + binding.get_locus ()); + binding_args.push_back (std::move (b)); + } + + for (auto &arg : args.get_generic_args ()) + { + switch (arg.get_kind ()) + { + case GenericArg::Kind::Type: { + std::unique_ptr<Type> ty = new_type (arg.get_type ()); + GenericArg arg = GenericArg::create_type (std::move (ty)); + } + break; + + default: + // FIXME + rust_unreachable (); + break; + } + } + + return GenericArgs (std::move (lifetime_args), std::move (generic_args), + std::move (binding_args), locus); +} + } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-ast-builder.h b/gcc/rust/ast/rust-ast-builder.h index 5c33954..682af79 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,36 +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> + 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> @@ -113,8 +254,53 @@ public: std::unique_ptr<Expr> field_access (std::unique_ptr<Expr> &&instance, std::string field) const; + std::unique_ptr<StructPatternField> + struct_pattern_ident_pattern (std::string field_name, + std::unique_ptr<Pattern> &&pattern); + /* 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, + std::vector<std::unique_ptr<TypeParamBound>> extra_trait_bounds = {}); + + static Lifetime new_lifetime (const Lifetime &lifetime); + + static GenericArgs new_generic_args (GenericArgs &args); private: /** diff --git a/gcc/rust/ast/rust-ast-collector.cc b/gcc/rust/ast/rust-ast-collector.cc index a2cb506..709908b 100644 --- a/gcc/rust/ast/rust-ast-collector.cc +++ b/gcc/rust/ast/rust-ast-collector.cc @@ -15,11 +15,17 @@ // 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" namespace Rust { namespace AST { @@ -248,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)); @@ -396,6 +379,9 @@ TokenCollector::visit (Token &tok) case BYTE_STRING_LITERAL: push (Rust::Token::make_byte_string (tok.get_locus (), std::move (data))); break; + case RAW_STRING_LITERAL: + push (Rust::Token::make_raw_string (tok.get_locus (), std::move (data))); + break; case INNER_DOC_COMMENT: push (Rust::Token::make_inner_doc_comment (tok.get_locus (), std::move (data))); @@ -475,6 +461,7 @@ TokenCollector::visit (LifetimeParam &lifetime_param) // TODO what to do with outer attr? They are not mentioned in the reference. + visit_items_as_lines (lifetime_param.get_outer_attrs ()); auto lifetime = lifetime_param.get_lifetime (); visit (lifetime); @@ -494,6 +481,7 @@ TokenCollector::visit (ConstGenericParam ¶m) // Syntax: // const IDENTIFIER : Type ( = Block | IDENTIFIER | -?LITERAL )? + visit_items_as_lines (param.get_outer_attrs ()); push (Rust::Token::make (CONST, param.get_locus ())); auto id = param.get_name ().as_string (); push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (id))); @@ -503,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 ()); } } @@ -545,11 +533,23 @@ TokenCollector::visit (PathExprSegment &segment) void TokenCollector::visit (PathInExpression &path) { - if (path.opening_scope_resolution ()) + if (path.is_lang_item ()) { - push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); + push (Rust::Token::make (TokenId::HASH, path.get_locus ())); + push (Rust::Token::make (TokenId::LEFT_SQUARE, path.get_locus ())); + push (Rust::Token::make_identifier (path.get_locus (), "lang")); + push (Rust::Token::make (TokenId::EQUAL, path.get_locus ())); + push ( + Rust::Token::make_string (path.get_locus (), + LangItem::ToString (path.get_lang_item ()))); + push (Rust::Token::make (TokenId::RIGHT_SQUARE, path.get_locus ())); + + return; } + if (path.opening_scope_resolution ()) + push (Rust::Token::make (SCOPE_RESOLUTION, path.get_locus ())); + visit_items_joined_by_separator (path.get_segments (), SCOPE_RESOLUTION); } @@ -558,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 @@ -573,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)); @@ -632,8 +639,6 @@ TokenCollector::visit (GenericArg &arg) push (Rust::Token::make_identifier (UNDEF_LOCATION, std::move (path))); } break; - case GenericArg::Kind::Error: - rust_unreachable (); } } @@ -690,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 ())); } @@ -773,6 +778,9 @@ TokenCollector::visit (Literal &lit, location_t locus) case Literal::LitType::BYTE_STRING: push (Rust::Token::make_byte_string (locus, std::move (value))); break; + case Literal::LitType::RAW_STRING: + push (Rust::Token::make_raw_string (locus, std::move (value))); + break; case Literal::LitType::INT: push ( Rust::Token::make_int (locus, std::move (value), lit.get_type_hint ())); @@ -840,8 +848,21 @@ TokenCollector::visit (BorrowExpr &expr) push (Rust::Token::make (AMP, expr.get_locus ())); if (expr.get_is_double_borrow ()) push (Rust::Token::make (AMP, UNDEF_LOCATION)); - if (expr.get_is_mut ()) - push (Rust::Token::make (MUT, UNDEF_LOCATION)); + + if (expr.is_raw_borrow ()) + { + push (Rust::Token::make_identifier (expr.get_locus (), + Values::WeakKeywords::RAW)); + if (expr.get_is_mut ()) + push (Rust::Token::make (MUT, UNDEF_LOCATION)); + else + push (Rust::Token::make (CONST, UNDEF_LOCATION)); + } + else + { + if (expr.get_is_mut ()) + push (Rust::Token::make (MUT, UNDEF_LOCATION)); + } visit (expr.get_borrowed_expr ()); } @@ -1096,8 +1117,7 @@ TokenCollector::visit (StructExprStruct &expr) void TokenCollector::visit (StructExprFieldIdentifier &expr) { - // TODO: Add attributes - // visit_items_as_lines (expr.get_attrs ()); + visit_items_as_lines (expr.get_outer_attrs ()); auto id = expr.get_field_name ().as_string (); push (Rust::Token::make_identifier (expr.get_locus (), std::move (id))); } @@ -1105,8 +1125,7 @@ TokenCollector::visit (StructExprFieldIdentifier &expr) void TokenCollector::visit (StructExprFieldIdentifierValue &expr) { - // TODO: Add attributes - // visit_items_as_lines (expr.get_attrs ()); + visit_items_as_lines (expr.get_outer_attrs ()); auto id = expr.get_field_name (); push (Rust::Token::make_identifier (expr.get_locus (), std::move (id))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); @@ -1116,8 +1135,7 @@ TokenCollector::visit (StructExprFieldIdentifierValue &expr) void TokenCollector::visit (StructExprFieldIndexValue &expr) { - // TODO: Add attributes - // visit_items_as_lines (expr.get_attrs ()); + visit_items_as_lines (expr.get_outer_attrs ()); push (Rust::Token::make_int (expr.get_locus (), std::to_string (expr.get_index ()))); push (Rust::Token::make (COLON, UNDEF_LOCATION)); @@ -1246,6 +1264,22 @@ TokenCollector::visit (BlockExpr &expr) } void +TokenCollector::visit (AnonConst &expr) +{ + visit (expr.get_inner_expr ()); +} + +void +TokenCollector::visit (ConstBlock &expr) +{ + push (Rust::Token::make (CONST, expr.get_locus ())); + + // The inner expression is already a block expr, so we don't need to add + // curlies + visit (expr.get_const_expr ()); +} + +void TokenCollector::visit (ClosureExprInnerTyped &expr) { visit_closure_common (expr); @@ -1259,7 +1293,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 @@ -1267,7 +1301,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 ()); } @@ -1316,6 +1350,13 @@ TokenCollector::visit (RangeToInclExpr &expr) } void +TokenCollector::visit (BoxExpr &expr) +{ + push (Rust::Token::make (BOX, expr.get_locus ())); + visit (expr.get_boxed_expr ()); +} + +void TokenCollector::visit (ReturnExpr &expr) { push (Rust::Token::make (RETURN_KW, expr.get_locus ())); @@ -1491,6 +1532,132 @@ TokenCollector::visit (AsyncBlockExpr &expr) visit (expr.get_block_expr ()); } +void +TokenCollector::visit (InlineAsm &expr) +{ + push (Rust::Token::make_identifier (expr.get_locus (), "asm")); + push (Rust::Token::make (EXCLAM, expr.get_locus ())); + push (Rust::Token::make (LEFT_PAREN, expr.get_locus ())); + + for (auto &template_str : expr.get_template_strs ()) + push (Rust::Token::make_string (template_str.get_locus (), + std::move (template_str.symbol))); + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &operand : expr.get_operands ()) + { + using RegisterType = AST::InlineAsmOperand::RegisterType; + switch (operand.get_register_type ()) + { + case RegisterType::In: { + visit (operand.get_in ().expr); + break; + } + case RegisterType::Out: { + visit (operand.get_out ().expr); + break; + } + case RegisterType::InOut: { + visit (operand.get_in_out ().expr); + break; + } + case RegisterType::SplitInOut: { + auto split = operand.get_split_in_out (); + visit (split.in_expr); + visit (split.out_expr); + break; + } + case RegisterType::Const: { + visit (operand.get_const ().anon_const.get_inner_expr ()); + break; + } + case RegisterType::Sym: { + visit (operand.get_sym ().expr); + break; + } + case RegisterType::Label: { + visit (operand.get_label ().expr); + break; + } + } + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &clobber : expr.get_clobber_abi ()) + { + 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 ())); + + for (auto it = expr.named_args.begin (); it != expr.named_args.end (); ++it) + { + auto &arg = *it; + push ( + Rust::Token::make_identifier (expr.get_locus (), arg.first.c_str ())); + push (Rust::Token::make (EQUAL, expr.get_locus ())); + push (Rust::Token::make_identifier (expr.get_locus (), + std::to_string (arg.second))); + + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (COLON, expr.get_locus ())); + + for (auto &option : expr.get_options ()) + { + push (Rust::Token::make_identifier ( + expr.get_locus (), InlineAsm::option_to_string (option).c_str ())); + push (Rust::Token::make (COMMA, expr.get_locus ())); + } + + push (Rust::Token::make (RIGHT_PAREN, expr.get_locus ())); +} + +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 @@ -1501,6 +1668,7 @@ TokenCollector::visit (TypeParam ¶m) // TypeParamBounds : // TypeParamBound ( + TypeParamBound )* +? + visit_items_as_lines (param.get_outer_attrs ()); auto id = param.get_type_representation ().as_string (); push (Rust::Token::make_identifier (param.get_locus (), std::move (id))); if (param.has_type_param_bounds ()) @@ -2453,10 +2621,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 @@ -2559,6 +2724,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 fdc99bb..fa835ce 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); @@ -278,6 +277,8 @@ public: void visit (ClosureParam ¶m); void visit (ClosureExprInner &expr); void visit (BlockExpr &expr); + void visit (AnonConst &expr); + void visit (ConstBlock &expr); void visit (ClosureExprInnerTyped &expr); void visit (ContinueExpr &expr); void visit (BreakExpr &expr); @@ -288,6 +289,7 @@ public: void visit (RangeFromToInclExpr &expr); void visit (RangeToInclExpr &expr); void visit (ReturnExpr &expr); + void visit (BoxExpr &expr); void visit (UnsafeBlockExpr &expr); void visit (LoopExpr &expr); void visit (WhileLoopExpr &expr); @@ -302,7 +304,8 @@ public: void visit (MatchExpr &expr); 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-fragment.h b/gcc/rust/ast/rust-ast-fragment.h index 33603ac..8dde9ed 100644 --- a/gcc/rust/ast/rust-ast-fragment.h +++ b/gcc/rust/ast/rust-ast-fragment.h @@ -123,12 +123,25 @@ private: void assert_single_fragment (SingleASTNode::NodeType expected) const; }; +enum class InvocKind +{ + Expr, + Semicoloned, +}; + +enum class AsmKind +{ + Global, + Inline +}; + /** * This is the type for transcriber functions found in * rust-macro-builtins.{h,cc}. */ using MacroTranscriberFunc - = std::function<tl::optional<Fragment> (location_t, MacroInvocData &)>; + = std::function<tl::optional<Fragment> (location_t, MacroInvocData &, + InvocKind semicolon)>; } // namespace AST } // namespace Rust diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index dd982c4..aabb1e4 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -61,7 +61,7 @@ class PathIdentSegment; struct GenericArgsBinding; struct GenericArgs; class PathExprSegment; -class PathPattern; +class Path; class PathInExpression; class TypePathSegment; class TypePathSegmentGeneric; @@ -115,6 +115,8 @@ struct ClosureParam; class ClosureExpr; class ClosureExprInner; class BlockExpr; +class AnonConst; +class ConstBlock; class ClosureExprInnerTyped; class ContinueExpr; class BreakExpr; @@ -145,10 +147,9 @@ struct MatchCase; class MatchExpr; class AwaitExpr; class AsyncBlockExpr; -enum class InlineAsmOptions; -struct AnonConst; +enum class InlineAsmOption; struct InlineAsmRegOrRegClass; -struct InlineAsmOperand; +class InlineAsmOperand; struct InlineAsmPlaceHolder; struct InlineAsmTemplatePiece; struct TupleClobber; @@ -202,7 +203,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 de4242a..7caa54b 100644 --- a/gcc/rust/ast/rust-ast-visitor.cc +++ b/gcc/rust/ast/rust-ast-visitor.cc @@ -69,7 +69,7 @@ DefaultASTVisitor::visit (AST::Lifetime &lifetime) void DefaultASTVisitor::visit (AST::LifetimeParam &lifetime_param) { - visit (lifetime_param.get_outer_attribute ()); + visit_outer_attrs (lifetime_param); visit (lifetime_param.get_lifetime ()); for (auto &lifetime_bound : lifetime_param.get_lifetime_bounds ()) visit (lifetime_bound); @@ -78,19 +78,21 @@ DefaultASTVisitor::visit (AST::LifetimeParam &lifetime_param) void DefaultASTVisitor::visit (AST::ConstGenericParam &const_param) { - visit (const_param.get_outer_attribute ()); + visit_outer_attrs (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::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 @@ -106,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 @@ -390,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 ()) @@ -401,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 ()); } @@ -451,6 +456,18 @@ DefaultASTVisitor::visit (AST::BlockExpr &expr) } void +DefaultASTVisitor::visit (AST::ConstBlock &expr) +{ + visit (expr.get_const_expr ()); +} + +void +DefaultASTVisitor::visit (AST::AnonConst &expr) +{ + visit (expr.get_inner_expr ()); +} + +void DefaultASTVisitor::visit (AST::ClosureExprInnerTyped &expr) { visit_outer_attrs (expr); @@ -473,7 +490,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 @@ -481,7 +499,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 ()); @@ -532,6 +550,13 @@ DefaultASTVisitor::visit (AST::ReturnExpr &expr) } void +DefaultASTVisitor::visit (AST::BoxExpr &expr) +{ + visit_outer_attrs (expr); + visit (expr.get_boxed_expr ()); +} + +void DefaultASTVisitor::visit (AST::UnsafeBlockExpr &expr) { visit_outer_attrs (expr); @@ -548,7 +573,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 ()); } @@ -556,8 +582,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 ()); } @@ -567,8 +594,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 ()); } @@ -578,7 +605,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 ()); } @@ -656,9 +684,62 @@ DefaultASTVisitor::visit (AST::AsyncBlockExpr &expr) } void +DefaultASTVisitor::visit (AST::InlineAsm &expr) +{ + visit_outer_attrs (expr); + using RegisterType = AST::InlineAsmOperand::RegisterType; + for (auto &operand : expr.get_operands ()) + { + switch (operand.get_register_type ()) + { + case RegisterType::In: { + visit (operand.get_in ().expr); + break; + } + case RegisterType::Out: { + visit (operand.get_out ().expr); + break; + } + case RegisterType::InOut: { + visit (operand.get_in_out ().expr); + break; + } + case RegisterType::SplitInOut: { + auto split = operand.get_split_in_out (); + visit (split.in_expr); + visit (split.out_expr); + break; + } + case RegisterType::Const: { + visit (operand.get_const ().anon_const.get_inner_expr ()); + break; + } + case RegisterType::Sym: { + visit (operand.get_sym ().expr); + break; + } + case RegisterType::Label: { + visit (operand.get_label ().expr); + break; + } + } + } +} + +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 (param.get_outer_attribute ()); + visit_outer_attrs (param); for (auto &bound : param.get_type_param_bounds ()) visit (bound); if (param.has_type ()) @@ -686,7 +767,8 @@ DefaultASTVisitor::visit (AST::TypeBoundWhereClauseItem &item) void DefaultASTVisitor::visit (AST::Visibility &vis) { - visit (vis.get_path ()); + if (vis.has_path ()) + visit (vis.get_path ()); } void @@ -759,10 +841,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); @@ -770,10 +860,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 ()) @@ -846,7 +935,7 @@ DefaultASTVisitor::visit (AST::EnumItem &item) void DefaultASTVisitor::visit (AST::EnumItemTuple &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item)); for (auto &field : item.get_tuple_fields ()) visit (field); } @@ -854,7 +943,7 @@ DefaultASTVisitor::visit (AST::EnumItemTuple &item) void DefaultASTVisitor::visit (AST::EnumItemStruct &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item)); for (auto &field : item.get_struct_fields ()) visit (field); } @@ -862,7 +951,7 @@ DefaultASTVisitor::visit (AST::EnumItemStruct &item) void DefaultASTVisitor::visit (AST::EnumItemDiscriminant &item) { - visit (reinterpret_cast<EnumItem &> (item)); + DefaultASTVisitor::visit (reinterpret_cast<EnumItem &> (item)); visit (item.get_expr ()); } @@ -936,6 +1025,8 @@ DefaultASTVisitor::visit (AST::Trait &trait) visit_inner_attrs (trait); + visit (trait.get_implicit_self ()); + for (auto &generic : trait.get_generic_params ()) visit (generic); @@ -976,6 +1067,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); @@ -997,14 +1089,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); @@ -1392,33 +1476,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 622e7f7..2a3c744 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -24,7 +24,9 @@ #include "rust-ast-full-decls.h" #include "rust-ast.h" #include "rust-item.h" +#include "rust-path.h" #include "rust-system.h" +#include "rust-stacked-contexts.h" namespace Rust { namespace AST { @@ -102,6 +104,8 @@ public: virtual void visit (FieldAccessExpr &expr) = 0; virtual void visit (ClosureExprInner &expr) = 0; virtual void visit (BlockExpr &expr) = 0; + virtual void visit (AnonConst &expr) = 0; + virtual void visit (ConstBlock &expr) = 0; virtual void visit (ClosureExprInnerTyped &expr) = 0; virtual void visit (ContinueExpr &expr) = 0; virtual void visit (BreakExpr &expr) = 0; @@ -112,6 +116,7 @@ public: virtual void visit (RangeFromToInclExpr &expr) = 0; virtual void visit (RangeToInclExpr &expr) = 0; virtual void visit (ReturnExpr &expr) = 0; + virtual void visit (BoxExpr &expr) = 0; virtual void visit (UnsafeBlockExpr &expr) = 0; virtual void visit (LoopExpr &expr) = 0; virtual void visit (WhileLoopExpr &expr) = 0; @@ -127,6 +132,8 @@ public: virtual void visit (MatchExpr &expr) = 0; 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; @@ -237,9 +244,10 @@ public: class DefaultASTVisitor : public ASTVisitor { public: + virtual void visit_function_params (AST::Function &function); + virtual void visit (AST::Crate &crate); -protected: virtual void visit (AST::Token &tok) override; virtual void visit (AST::DelimTokenTree &delim_tok_tree) override; virtual void visit (AST::AttrInputMetaItemContainer &input) override; @@ -287,6 +295,8 @@ protected: virtual void visit (AST::FieldAccessExpr &expr) override; virtual void visit (AST::ClosureExprInner &expr) override; virtual void visit (AST::BlockExpr &expr) override; + virtual void visit (AST::AnonConst &expr) override; + virtual void visit (AST::ConstBlock &expr) override; virtual void visit (AST::ClosureExprInnerTyped &expr) override; virtual void visit (AST::ContinueExpr &expr) override; virtual void visit (AST::BreakExpr &expr) override; @@ -297,6 +307,7 @@ protected: virtual void visit (AST::RangeFromToInclExpr &expr) override; virtual void visit (AST::RangeToInclExpr &expr) override; virtual void visit (AST::ReturnExpr &expr) override; + virtual void visit (AST::BoxExpr &expr) override; virtual void visit (AST::UnsafeBlockExpr &expr) override; virtual void visit (AST::LoopExpr &expr) override; virtual void visit (AST::WhileLoopExpr &expr) override; @@ -309,6 +320,9 @@ protected: virtual void visit (AST::MatchExpr &expr) override; 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; virtual void visit (AST::TypeBoundWhereClauseItem &item) override; @@ -418,7 +432,6 @@ protected: 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); @@ -443,7 +456,7 @@ protected: class ContextualASTVisitor : public DefaultASTVisitor { protected: - enum class Context + enum class Kind { FUNCTION, INHERENT_IMPL, @@ -452,6 +465,7 @@ protected: MODULE, CRATE, }; + using DefaultASTVisitor::visit; virtual void visit (AST::Crate &crate) override; @@ -467,11 +481,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 326379c..5b797e8 100644 --- a/gcc/rust/ast/rust-ast.cc +++ b/gcc/rust/ast/rust-ast.cc @@ -20,6 +20,8 @@ along with GCC; see the file COPYING3. If not see #include "rust-ast.h" #include "optional.h" #include "rust-builtin-ast-nodes.h" +#include "rust-common.h" +#include "rust-expr.h" #include "rust-system.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" @@ -270,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 ()); @@ -309,7 +311,8 @@ Attribute::get_traits_to_derive () // Copy constructor must deep copy attr_input as unique pointer Attribute::Attribute (Attribute const &other) - : path (other.path), locus (other.locus) + : path (other.path), locus (other.locus), + inner_attribute (other.inner_attribute) { // guard to protect from null pointer dereference if (other.attr_input != nullptr) @@ -322,6 +325,7 @@ Attribute::operator= (Attribute const &other) { path = other.path; locus = other.locus; + inner_attribute = other.inner_attribute; // guard to protect from null pointer dereference if (other.attr_input != nullptr) attr_input = other.attr_input->clone_attr_input (); @@ -1064,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) @@ -1096,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) @@ -1268,6 +1272,18 @@ BlockExpr::as_string () const } std::string +AnonConst::as_string () const +{ + return "AnonConst: " + expr->as_string (); +} + +std::string +ConstBlock::as_string () const +{ + return "ConstBlock: " + expr.as_string (); +} + +std::string TraitImpl::as_string () const { std::string str = VisItem::as_string (); @@ -1570,18 +1586,37 @@ BorrowExpr::as_string () const std::string str ("&"); - if (double_borrow) - str += "&"; - - if (is_mut) - str += "mut "; + if (raw_borrow) + { + str += "raw "; + str += get_is_mut () ? "const " : "mut "; + } + else + { + if (double_borrow) + str += "&"; + if (get_is_mut ()) + str += "mut "; + } str += main_or_left_expr->as_string (); return str; } std::string +BoxExpr::as_string () const +{ + return "box " + expr->as_string (); +} + +void +BoxExpr::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +std::string ReturnExpr::as_string () const { /* TODO: find way to incorporate outer attrs - may have to represent in @@ -1608,7 +1643,7 @@ ContinueExpr::as_string () const std::string str ("continue "); if (has_label ()) - str += label.as_string (); + str += get_label_unchecked ().as_string (); return str; } @@ -2072,7 +2107,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 (); @@ -2092,7 +2127,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 ()) @@ -2123,7 +2158,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 (); @@ -2160,7 +2195,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 (); @@ -2387,11 +2422,11 @@ LifetimeParam::as_string () const { std::string str ("LifetimeParam: "); - str += "\n Outer attribute: "; + str += "\n Outer attribute:"; if (!has_outer_attribute ()) str += "none"; - else - str += outer_attr.as_string (); + for (auto &attr : outer_attrs) + str += " " + attr.as_string (); str += "\n Lifetime: " + lifetime.as_string (); @@ -2462,9 +2497,6 @@ MacroMatchRepetition::as_string () const std::string Lifetime::as_string () const { - if (is_error ()) - return "error lifetime"; - switch (lifetime_type) { case NAMED: @@ -2483,11 +2515,11 @@ TypeParam::as_string () const { std::string str ("TypeParam: "); - str += "\n Outer attribute: "; + str += "\n Outer attribute:"; if (!has_outer_attribute ()) str += "none"; - else - str += outer_attr.as_string (); + for (auto &attr : outer_attrs) + str += " " + attr.as_string (); str += "\n Identifier: " + type_representation.as_string (); @@ -2522,7 +2554,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 (); @@ -2589,7 +2621,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 "; @@ -2694,7 +2726,7 @@ ImplTraitTypeOneBound::as_string () const { std::string str ("ImplTraitTypeOneBound: \n TraitBound: "); - return str + trait_bound.as_string (); + return str + trait_bound->as_string (); } std::string @@ -2975,22 +3007,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 @@ -3063,7 +3079,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 "; @@ -3485,6 +3501,7 @@ AttributeParser::parse_meta_item_inner () case STRING_LITERAL: case BYTE_CHAR_LITERAL: case BYTE_STRING_LITERAL: + case RAW_STRING_LITERAL: case INT_LITERAL: case FLOAT_LITERAL: case TRUE_LITERAL: @@ -3767,6 +3784,10 @@ AttributeParser::parse_literal () skip_token (); return Literal (tok->as_string (), Literal::BYTE_STRING, tok->get_type_hint ()); + case RAW_STRING_LITERAL: + skip_token (); + return Literal (tok->as_string (), Literal::RAW_STRING, + tok->get_type_hint ()); case INT_LITERAL: skip_token (); return Literal (tok->as_string (), Literal::INT, tok->get_type_hint ()); @@ -4258,7 +4279,7 @@ BlockExpr::normalize_tail_expr () if (!stmt.is_semicolon_followed ()) { - expr = std::move (stmt.take_expr ()); + expr = stmt.take_expr (); statements.pop_back (); } } @@ -4504,6 +4525,18 @@ BlockExpr::accept_vis (ASTVisitor &vis) } void +AnonConst::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstBlock::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +void ClosureExprInnerTyped::accept_vis (ASTVisitor &vis) { vis.visit (*this); @@ -4636,6 +4669,18 @@ AsyncBlockExpr::accept_vis (ASTVisitor &vis) } void +InlineAsm::accept_vis (ASTVisitor &vis) +{ + vis.visit (*this); +} + +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 edf726b..49dfcde 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 { @@ -250,6 +231,7 @@ public: { case STRING_LITERAL: case BYTE_STRING_LITERAL: + case RAW_STRING_LITERAL: return true; default: return false; @@ -311,6 +293,7 @@ public: STRING, BYTE, BYTE_STRING, + RAW_STRING, INT, FLOAT, BOOL, @@ -374,7 +357,7 @@ public: // TODO: put checks in constructor to enforce this rule? SimplePathSegment (std::string segment_name, location_t locus) : segment_name (std::move (segment_name)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} /* Returns whether simple path segment is in an invalid state (currently, if @@ -420,19 +403,19 @@ class SimplePath public: // Constructor - SimplePath (std::vector<SimplePathSegment> path_segments, - bool has_opening_scope_resolution = false, - location_t locus = UNDEF_LOCATION) + explicit SimplePath (std::vector<SimplePathSegment> path_segments, + bool has_opening_scope_resolution = false, + location_t locus = UNDEF_LOCATION) : opening_scope_resolution (has_opening_scope_resolution), segments (std::move (path_segments)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} - SimplePath (Identifier ident) + explicit SimplePath (Identifier ident) : opening_scope_resolution (false), segments ({SimplePathSegment (ident.as_string (), ident.get_locus ())}), locus (ident.get_locus ()), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Creates an empty SimplePath. @@ -679,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; } @@ -1037,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 @@ -1090,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 @@ -1127,7 +1114,7 @@ public: virtual void add_semicolon () {} protected: - Stmt () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + Stmt () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Clone function implementation as pure virtual method virtual Stmt *clone_stmt_impl () const = 0; @@ -1139,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 { @@ -1219,14 +1228,67 @@ 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, + ConstExpr, + ConstBlock, + 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 { @@ -1264,7 +1326,7 @@ public: protected: // Constructor - Expr () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + Expr () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Clone function implementation as pure virtual method virtual Expr *clone_expr_impl () const = 0; @@ -1341,7 +1403,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 @@ -1408,7 +1470,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 @@ -1437,7 +1499,7 @@ public: NodeId get_node_id () const { return node_id; } protected: - Type () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + Type () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Clone function implementation as pure virtual method virtual Type *clone_type_impl () const = 0; @@ -1475,6 +1537,12 @@ protected: class TypeParamBound : public Visitable { public: + enum TypeParamBoundType + { + TRAIT, + LIFETIME + }; + virtual ~TypeParamBound () {} // Unique pointer custom clone function @@ -1489,6 +1557,8 @@ public: virtual location_t get_locus () const = 0; + virtual TypeParamBoundType get_bound_type () const = 0; + protected: // Clone function implementation as pure virtual method virtual TypeParamBound *clone_type_param_bound_impl () const = 0; @@ -1519,7 +1589,7 @@ public: // Constructor Lifetime (LifetimeType type, std::string name = std::string (), location_t locus = UNDEF_LOCATION) - : TypeParamBound (Analysis::Mappings::get ()->get_next_node_id ()), + : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()), lifetime_type (type), lifetime_name (std::move (name)), locus (locus) {} @@ -1529,27 +1599,24 @@ 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; - LifetimeType get_lifetime_type () { return lifetime_type; } + LifetimeType get_lifetime_type () const { return lifetime_type; } location_t get_locus () const override final { return locus; } std::string get_lifetime_name () const { return lifetime_name; } + TypeParamBoundType get_bound_type () const override + { + return TypeParamBound::TypeParamBoundType::LIFETIME; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1585,10 +1652,10 @@ public: virtual Kind get_kind () const = 0; - NodeId get_node_id () { return node_id; } + NodeId get_node_id () const { return node_id; } protected: - GenericParam () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + GenericParam () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} GenericParam (NodeId node_id) : node_id (node_id) {} // Clone function implementation as pure virtual method @@ -1602,7 +1669,7 @@ class LifetimeParam : public GenericParam { Lifetime lifetime; std::vector<Lifetime> lifetime_bounds; - Attribute outer_attr; + AST::AttrVec outer_attrs; location_t locus; public: @@ -1610,32 +1677,27 @@ public: Lifetime &get_lifetime () { return lifetime; } - Attribute &get_outer_attribute () { return outer_attr; } + AST::AttrVec &get_outer_attrs () { return outer_attrs; } // Returns whether the lifetime param has any lifetime bounds. bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); } std::vector<Lifetime> &get_lifetime_bounds () { return lifetime_bounds; } - // Returns whether the lifetime param has an outer attribute. - bool has_outer_attribute () const { return !outer_attr.is_empty (); } - - // Creates an error state lifetime param. - static LifetimeParam create_error () + const std::vector<Lifetime> &get_lifetime_bounds () const { - return LifetimeParam (Lifetime::error (), {}, Attribute::create_empty (), - UNDEF_LOCATION); + return lifetime_bounds; } - // Returns whether the lifetime param is in an error state. - bool is_error () const { return lifetime.is_error (); } + // Returns whether the lifetime param has an outer attribute. + bool has_outer_attribute () const { return !outer_attrs.empty (); } // Constructor LifetimeParam (Lifetime lifetime, std::vector<Lifetime> lifetime_bounds, - Attribute outer_attr, location_t locus) + AST::AttrVec outer_attrs, location_t locus) : lifetime (std::move (lifetime)), lifetime_bounds (std::move (lifetime_bounds)), - outer_attr (std::move (outer_attr)), locus (locus) + outer_attrs (std::move (outer_attrs)), locus (locus) {} std::string as_string () const override; @@ -1682,12 +1744,12 @@ class TraitItem : public AssociatedItem { protected: TraitItem (location_t locus) - : node_id (Analysis::Mappings::get ()->get_next_node_id ()), + : node_id (Analysis::Mappings::get ().get_next_node_id ()), vis (Visibility::create_private ()), locus (locus) {} TraitItem (Visibility vis, location_t locus) - : node_id (Analysis::Mappings::get ()->get_next_node_id ()), vis (vis), + : node_id (Analysis::Mappings::get ().get_next_node_id ()), vis (vis), locus (locus) {} @@ -1713,7 +1775,7 @@ public: class ExternalItem : public Visitable { public: - ExternalItem () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + ExternalItem () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} ExternalItem (NodeId node_id) : node_id (node_id) {} @@ -1929,13 +1991,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 ()); @@ -1948,16 +2003,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 ()); @@ -1987,7 +2032,7 @@ public: Crate (std::vector<std::unique_ptr<Item>> items, std::vector<Attribute> inner_attrs) : inner_attrs (std::move (inner_attrs)), items (std::move (items)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Copy constructor with vector clone @@ -2047,11 +2092,6 @@ public: } }; -// Base path expression AST node - abstract -class PathExpr : public ExprWithoutBlock -{ -}; - } // namespace AST } // namespace Rust @@ -2064,6 +2104,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 3e21d7e..df3db85 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..306c6f7 --- /dev/null +++ b/gcc/rust/ast/rust-collect-lang-items.cc @@ -0,0 +1,137 @@ +// 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); +} + +void +CollectLangItems::visit (AST::EnumItemTuple &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemStruct &item) +{ + maybe_add_lang_item (item); + + DefaultASTVisitor::visit (item); +} + +void +CollectLangItems::visit (AST::EnumItemDiscriminant &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..ddc7b51 --- /dev/null +++ b/gcc/rust/ast/rust-collect-lang-items.h @@ -0,0 +1,64 @@ +// 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; + void visit (AST::EnumItemTuple &item) override; + void visit (AST::EnumItemStruct &item) override; + void visit (AST::EnumItemDiscriminant &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-apit.cc b/gcc/rust/ast/rust-desugar-apit.cc new file mode 100644 index 0000000..5b9486e --- /dev/null +++ b/gcc/rust/ast/rust-desugar-apit.cc @@ -0,0 +1,518 @@ +// 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-apit.h" +#include "rust-ast.h" +#include "rust-type.h" + +namespace Rust { +namespace AST { + +class DesugarApitType : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + static std::pair<AST::Type *, std::vector<std::unique_ptr<GenericParam>>> + Desugar (AST::Type &type) + { + DesugarApitType visitor (&type); + type.accept_vis (visitor); + rust_assert (visitor.translated != nullptr); + return std::make_pair (visitor.translated, + std::move (visitor.implicit_generic_params)); + } + + // Generate a unique impl trait parameter name + static Identifier get_impl_name () + { + static size_t counter = 0; + return Identifier ("Impl_" + std::to_string (counter++)); + } + + // these can hold other types + void visit (AST::TupleType &tuple) override + { + for (auto &elem : tuple.get_elems ()) + { + auto &type = *elem.get (); + auto desugar = Desugar (type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + continue; + + if (tt != elem.get ()) + elem = std::unique_ptr<Type> (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + } + + void visit (AST::ArrayType &type) override + { + auto &element_type = type.get_element_type (); + auto desugar = Desugar (*element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (tt != element_type.get ()) + element_type = std::unique_ptr<AST::Type> (tt); + + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ReferenceType &type) override + { + // Get a reference to the current type for in-place modification + auto &referenced_type = type.get_type_referenced (); + auto desugar = Desugar (referenced_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the reference type's contents rather than creating a new one + if (&referenced_type != tt) + { + std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds ( + static_cast<AST::TypeNoBounds *> (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::RawPointerType &type) override + { + auto &pointed_type = type.get_type_pointed_to (); + auto desugar = Desugar (pointed_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + // Update the pointer's inner type directly using the new accessor + if (&pointed_type != tt) + { + std::unique_ptr<AST::TypeNoBounds> new_type_no_bounds ( + static_cast<AST::TypeNoBounds *> (tt)); + type.get_type_ptr () = std::move (new_type_no_bounds); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::SliceType &type) override + { + auto &element_type = type.get_elem_type (); + auto desugar = Desugar (element_type); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (&element_type != tt) + { + std::unique_ptr<AST::Type> new_elem_type (tt); + type.get_elem_type_ptr () = std::move (new_elem_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + void visit (AST::ParenthesisedType &type) override + { + auto &inner_type_ptr = type.get_type_in_parens (); + auto desugar = Desugar (*inner_type_ptr); + auto tt = desugar.first; + + auto &implicit_generics = desugar.second; + if (implicit_generics.empty ()) + return; + + if (inner_type_ptr.get () != tt) + { + std::unique_ptr<AST::Type> new_inner_type (tt); + inner_type_ptr = std::move (new_inner_type); + } + + // Collect all the implicit generic parameters we found + for (auto &implicit_generic : implicit_generics) + implicit_generic_params.push_back (std::move (implicit_generic)); + } + + // this is where the desugar happens + void visit (AST::ImplTraitType &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( + PathIdentSegment (ident.as_string (), type.get_locus ()), false, + type.get_locus ()))); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert bounds from impl trait to generic parameter bounds + std::vector<std::unique_ptr<TypeParamBound>> bounds; + for (auto &bound : type.get_type_param_bounds ()) + bounds.push_back (bound->clone_type_param_bound ()); + + // Create the new generic parameter + auto generic_param = std::unique_ptr<TypeParam> ( + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + + void visit (AST::ImplTraitTypeOneBound &type) override + { + // Generate a unique name using the static method + auto ident = get_impl_name (); + + // Create a type path for the new generic parameter + // Create a SimplePathSegment with the identifier string + auto simple_seg = SimplePathSegment (ident.as_string (), type.get_locus ()); + // Create a vector of SimplePathSegments for SimplePath constructor + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + // Create a SimplePath + auto simple_path = SimplePath (simple_segs, false, type.get_locus ()); + + // Convert to TypePath by creating path segments + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( + PathIdentSegment (ident.as_string (), type.get_locus ()), false, + type.get_locus ()))); + + // Create TypePath from segments + auto type_path + = new TypePath (std::move (segments), type.get_locus (), false); + + // Convert the bound to a generic parameter bound + std::vector<std::unique_ptr<TypeParamBound>> bounds; + bounds.push_back (std::move (type.get_trait_bound ())); + + // Create the new generic parameter + auto generic_param = std::unique_ptr<TypeParam> ( + new TypeParam (ident, type.get_locus (), std::move (bounds), nullptr, {}, + true /*from impl trait*/)); + + // Store the generic parameter to be added to the function signature + implicit_generic_params.push_back (std::move (generic_param)); + + // Replace impl trait with the new type parameter + translated = type_path; + } + +private: + DesugarApitType (AST::Type *base) + : translated (base), implicit_generic_params () + {} + + AST::Type *translated; + std::vector<std::unique_ptr<GenericParam>> implicit_generic_params; +}; + +// --------- + +class ApitBoundProcessor +{ +public: + ApitBoundProcessor ( + WhereClause &where_clause, + std::vector<std::unique_ptr<GenericParam>> &generic_params) + : where_clause (where_clause), generic_params (generic_params) + {} + + void go (std::vector<std::unique_ptr<GenericParam>> &implicit_generics) + { + // some desugars are more complex so imagine this case + // + // pub fn foo(_value: impl Bar<Baz = impl Foo>) -> i32 { + // 15 + // } + // + // this needs to become: + // + // pub fn foo<T, U>(_value: T) -> i32 + // where + // T: Bar<Baz = U>, + // U: Foo, + // { + // 15 + // } + // + // so we need to walk all the implicit generics and the trait bounds paths + // for more generics + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: { + TypeParam &p + = *static_cast<TypeParam *> (implicit_generic.get ()); + + process_type_param (p); + generic_params.push_back (std::move (implicit_generic)); + for (auto &synth : synthetic_params) + generic_params.push_back (std::move (synth)); + synthetic_params.clear (); + } + break; + + default: + generic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + +private: + void process_type_param (TypeParam &p) + { + auto &bounds = p.get_type_param_bounds (); + std::vector<size_t> bounds_to_remove; + for (size_t i = 0; i < bounds.size (); i++) + { + auto &tb = bounds[i]; + switch (tb->get_bound_type ()) + { + case TypeParamBound::TypeParamBoundType::TRAIT: { + TraitBound &ttb = *static_cast<TraitBound *> (tb.get ()); + TypePath &path = ttb.get_type_path (); + bool deusgared = process_type_path (p, ttb, path); + if (deusgared) + bounds_to_remove.push_back (i); + } + + default: + break; + } + } + for (auto it = bounds_to_remove.rbegin (); it != bounds_to_remove.rend (); + ++it) + bounds.erase (bounds.begin () + *it); + } + + bool process_type_path (TypeParam &p, TraitBound &parent, TypePath &path) + { + bool desugared = false; + for (auto &segment : path.get_segments ()) + { + switch (segment->get_type ()) + { + case TypePathSegment::SegmentType::GENERIC: { + TypePathSegmentGeneric &seg + = *static_cast<TypePathSegmentGeneric *> (segment.get ()); + desugared |= process_generic_segment (p, parent, path, seg); + } + + default: + break; + } + } + return desugared; + } + + bool process_generic_segment (TypeParam &p, TraitBound &parent, + TypePath &path, TypePathSegmentGeneric &seg) + { + // we need to look for any impl types as default arguments in any generics + // and remove this index from the generic arguments by using a where + // constraint instead + + std::vector<std::unique_ptr<WhereClauseItem>> new_clauses; + GenericArgs &generic_args = seg.get_generic_args (); + std::vector<std::reference_wrapper<const GenericArgsBinding>> + bindings_desugared; + std::vector<GenericArgsBinding> &bindings + = generic_args.get_binding_args (); + + for (auto &generic : bindings) + { + auto &t = generic.get_type (); + auto translated = DesugarApitType::Desugar (t); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (tt != &t) + { + bindings_desugared.push_back (generic); + generic.get_type_ptr () = std::unique_ptr<Type> (tt); + } + + for (auto &implicit_generic : implicit_generics) + { + switch (implicit_generic->get_kind ()) + { + case GenericParam::Kind::Type: { + TypeParam &tp + = *static_cast<TypeParam *> (implicit_generic.get ()); + + std::vector<std::unique_ptr<TypeParamBound>> + type_param_bounds; + for (auto &b : tp.get_type_param_bounds ()) + type_param_bounds.push_back (std::move (b)); + tp.get_type_param_bounds ().clear (); + + // add synthetic parameter for this + synthetic_params.push_back (std::move (implicit_generic)); + + auto bound_type_path + = get_type_for_identifier (tp.get_type_representation ()); + + auto clause = new TypeBoundWhereClauseItem ( + {}, std::move (bound_type_path), + std::move (type_param_bounds), tp.get_locus ()); + std::unique_ptr<WhereClauseItem> clause_item + = std::unique_ptr<WhereClauseItem> (clause); + new_clauses.push_back (std::move (clause_item)); + } + break; + + default: + synthetic_params.push_back (std::move (implicit_generic)); + break; + } + } + } + + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; + auto bound = std::unique_ptr<TypeParamBound> (new TraitBound (parent)); + type_param_bounds.push_back (std::move (bound)); + auto parent_type_path + = get_type_for_identifier (p.get_type_representation ()); + auto clause + = new TypeBoundWhereClauseItem ({}, std::move (parent_type_path), + std::move (type_param_bounds), + parent.get_locus ()); + std::unique_ptr<WhereClauseItem> clause_item + = std::unique_ptr<WhereClauseItem> (clause); + where_clause.get_items ().push_back (std::move (clause_item)); + + for (auto &where_item : new_clauses) + where_clause.get_items ().push_back (std::move (where_item)); + + return !bindings_desugared.empty (); + } + + static std::unique_ptr<Type> get_type_for_identifier (const Identifier &ident) + { + auto simple_seg + = SimplePathSegment (ident.as_string (), ident.get_locus ()); + std::vector<SimplePathSegment> simple_segs = {simple_seg}; + auto simple_path = SimplePath (simple_segs, false, ident.get_locus ()); + std::vector<std::unique_ptr<TypePathSegment>> segments; + segments.push_back (std::unique_ptr<TypePathSegment> (new TypePathSegment ( + PathIdentSegment (ident.as_string (), ident.get_locus ()), false, + ident.get_locus ()))); + auto type_path = new TypePath (std::move (segments), ident.get_locus ()); + return std::unique_ptr<Type> (type_path); + } + +private: + WhereClause &where_clause; + std::vector<std::unique_ptr<GenericParam>> &generic_params; + + // mutates + std::vector<std::unique_ptr<GenericParam>> synthetic_params; +}; + +// --------- + +DesugarApit::DesugarApit () {} + +void +DesugarApit::go (AST::Crate &crate) +{ + DefaultASTVisitor::visit (crate); +} + +void +DesugarApit::visit (AST::Function &function) +{ + if (!function.has_function_params ()) + return; + + auto &fn_params = function.get_function_params (); + for (auto ¶m : fn_params) + { + if (param->is_variadic () || param->is_self ()) + continue; + + auto *p = param.get (); + auto &fp = *static_cast<AST::FunctionParam *> (p); + auto &type = fp.get_type (); + + auto translated = DesugarApitType::Desugar (type); + auto tt = translated.first; + + auto &implicit_generics = translated.second; + if (implicit_generics.empty ()) + continue; + + if (fp.get_type_ptr ().get () != tt) + { + fp.get_type_ptr () = std::unique_ptr<AST::Type> (tt); + } + + ApitBoundProcessor processor (function.get_where_clause (), + function.get_generic_params ()); + processor.go (implicit_generics); + } +} + +} // namespace AST +} // namespace Rust diff --git a/gcc/rust/ast/rust-macro.cc b/gcc/rust/ast/rust-desugar-apit.h index f36feda..07c25e2 100644 --- a/gcc/rust/ast/rust-macro.cc +++ b/gcc/rust/ast/rust-desugar-apit.h @@ -1,4 +1,4 @@ -// Copyright (C) 2020-2024 Free Software Foundation, Inc. +// Copyright (C) 2025 Free Software Foundation, Inc. // This file is part of GCC. @@ -16,10 +16,27 @@ // along with GCC; see the file COPYING3. If not see // <http://www.gnu.org/licenses/>. -#include "rust-macro.h" +#ifndef RUST_DESUGAR_APIT_H +#define RUST_DESUGAR_APIT_H + +#include "rust-ast-visitor.h" namespace Rust { namespace AST { +class DesugarApit : public DefaultASTVisitor +{ + using DefaultASTVisitor::visit; + +public: + DesugarApit (); + void go (AST::Crate &); + +private: + void visit (AST::Function &) override; +}; + } // namespace AST } // namespace Rust + +#endif // ! RUST_DESUGAR_APIT_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 d3dc197..ba20bfa 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -2,6 +2,7 @@ #define RUST_AST_EXPR_H #include "rust-ast.h" +#include "rust-common.h" #include "rust-path.h" #include "rust-macro.h" #include "rust-operators.h" @@ -14,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; @@ -26,15 +27,10 @@ public: LoopLabel (Lifetime loop_label, location_t locus = UNDEF_LOCATION) : label (std::move (loop_label)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // 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; } @@ -116,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 */ @@ -302,7 +300,7 @@ protected: class OperatorExpr : public ExprWithoutBlock { // TODO: create binary and unary operator subclasses? -public: +private: location_t locus; protected: @@ -364,24 +362,28 @@ 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 * overloaded. */ class BorrowExpr : public OperatorExpr { - bool is_mut; + Mutability mutability; + bool raw_borrow; bool double_borrow; public: std::string as_string () const override; - BorrowExpr (std::unique_ptr<Expr> borrow_lvalue, bool is_mut_borrow, - bool is_double_borrow, std::vector<Attribute> outer_attribs, - location_t locus) + BorrowExpr (std::unique_ptr<Expr> borrow_lvalue, Mutability mutability, + bool raw_borrow, bool is_double_borrow, + std::vector<Attribute> outer_attribs, location_t locus) : OperatorExpr (std::move (borrow_lvalue), std::move (outer_attribs), locus), - is_mut (is_mut_borrow), double_borrow (is_double_borrow) + mutability (mutability), raw_borrow (raw_borrow), + double_borrow (is_double_borrow) {} void accept_vis (ASTVisitor &vis) override; @@ -393,9 +395,14 @@ public: return *main_or_left_expr; } - bool get_is_mut () const { return is_mut; } + bool get_is_mut () const { return mutability == Mutability::Mut; } + + Mutability get_mutability () const { return mutability; } 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 @@ -427,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 */ @@ -458,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 */ @@ -501,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 */ @@ -589,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 */ @@ -676,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: @@ -764,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 */ @@ -826,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 */ @@ -904,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 */ @@ -990,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 */ @@ -1084,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 */ @@ -1113,7 +1149,7 @@ public: NodeId get_node_id () const { return node_id; } protected: - ArrayElems () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + ArrayElems () : node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // pure virtual clone implementation virtual ArrayElems *clone_array_elems_impl () const = 0; @@ -1178,6 +1214,8 @@ protected: class ArrayElemsCopied : public ArrayElems { std::unique_ptr<Expr> elem_to_copy; + + // TODO: This should be replaced by a ConstExpr std::unique_ptr<Expr> num_copies; location_t locus; @@ -1313,6 +1351,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 */ @@ -1418,6 +1458,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 */ @@ -1514,6 +1556,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 */ @@ -1601,6 +1645,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 */ @@ -1644,6 +1690,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! @@ -1758,13 +1806,26 @@ public: NodeId get_node_id () const { return node_id; } + const std::vector<AST::Attribute> &get_outer_attrs () const + { + return outer_attrs; + } + + std::vector<AST::Attribute> &get_outer_attrs () { return outer_attrs; } + protected: // pure virtual clone implementation virtual StructExprField *clone_struct_expr_field_impl () const = 0; - StructExprField () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) + StructExprField () : node_id (Analysis::Mappings::get ().get_next_node_id ()) + {} + + StructExprField (AST::AttrVec outer_attrs) + : outer_attrs (std::move (outer_attrs)), + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} + AST::AttrVec outer_attrs; NodeId node_id; }; @@ -1775,9 +1836,10 @@ class StructExprFieldIdentifier : public StructExprField location_t locus; public: - StructExprFieldIdentifier (Identifier field_identifier, location_t locus) - : StructExprField (), field_name (std::move (field_identifier)), - locus (locus) + StructExprFieldIdentifier (Identifier field_identifier, + AST::AttrVec outer_attrs, location_t locus) + : StructExprField (std::move (outer_attrs)), + field_name (std::move (field_identifier)), locus (locus) {} std::string as_string () const override { return field_name.as_string (); } @@ -1804,19 +1866,22 @@ class StructExprFieldWithVal : public StructExprField std::unique_ptr<Expr> value; protected: - StructExprFieldWithVal (std::unique_ptr<Expr> field_value) - : StructExprField (), value (std::move (field_value)) + StructExprFieldWithVal (std::unique_ptr<Expr> field_value, + AST::AttrVec outer_attrs) + : StructExprField (std::move (outer_attrs)), value (std::move (field_value)) {} // Copy constructor requires clone StructExprFieldWithVal (StructExprFieldWithVal const &other) - : value (other.value->clone_expr ()) + : StructExprField (other.get_outer_attrs ()), + value (other.value->clone_expr ()) {} // Overload assignment operator to clone unique_ptr StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other) { value = other.value->clone_expr (); + outer_attrs = other.get_outer_attrs (); return *this; } @@ -1845,8 +1910,15 @@ class StructExprFieldIdentifierValue : public StructExprFieldWithVal public: StructExprFieldIdentifierValue (Identifier field_identifier, std::unique_ptr<Expr> field_value, + AST::AttrVec outer_attrs, location_t locus) + : StructExprFieldWithVal (std::move (field_value), std::move (outer_attrs)), + field_name (std::move (field_identifier)), locus (locus) + {} + + StructExprFieldIdentifierValue (Identifier field_identifier, + std::unique_ptr<Expr> field_value, location_t locus) - : StructExprFieldWithVal (std::move (field_value)), + : StructExprFieldWithVal (std::move (field_value), {}), field_name (std::move (field_identifier)), locus (locus) {} @@ -1876,9 +1948,9 @@ class StructExprFieldIndexValue : public StructExprFieldWithVal public: StructExprFieldIndexValue (TupleIndex tuple_index, std::unique_ptr<Expr> field_value, - location_t locus) - : StructExprFieldWithVal (std::move (field_value)), index (tuple_index), - locus (locus) + AST::AttrVec outer_attrs, location_t locus) + : StructExprFieldWithVal (std::move (field_value), std::move (outer_attrs)), + index (tuple_index), locus (locus) {} std::string as_string () const override; @@ -2093,6 +2165,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; } @@ -2101,6 +2175,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 */ @@ -2204,6 +2280,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 */ @@ -2289,6 +2367,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 */ @@ -2424,6 +2504,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 @@ -2505,7 +2587,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; @@ -2522,8 +2604,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)), @@ -2642,8 +2725,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 @@ -2661,6 +2746,124 @@ protected: } }; +class AnonConst : public ExprWithBlock +{ +public: + AnonConst (std::unique_ptr<Expr> &&expr, location_t locus = UNKNOWN_LOCATION) + : ExprWithBlock (), locus (locus), expr (std::move (expr)) + { + rust_assert (this->expr); + } + + AnonConst (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + expr = other.expr->clone_expr (); + } + + AnonConst operator= (const AnonConst &other) + { + node_id = other.node_id; + locus = other.locus; + expr = other.expr->clone_expr (); + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstExpr; } + + location_t get_locus () const override { return locus; } + Expr &get_inner_expr () { return *expr; } + NodeId get_node_id () const override { return node_id; } + + /* FIXME: AnonConst are always "internal" and should not have outer attributes + * - is that true? Or should we instead call + * expr->get_outer_attrs()/expr->set_outer_attrs() */ + + std::vector<Attribute> &get_outer_attrs () override + { + static auto attrs = std::vector<Attribute> (); + return attrs; + } + + void set_outer_attrs (std::vector<Attribute>) override {} + + /* FIXME: Likewise for mark_for_strip() ? */ + void mark_for_strip () override {} + bool is_marked_for_strip () const override { return false; } + + void accept_vis (ASTVisitor &vis) override; + +private: + location_t locus; + std::unique_ptr<Expr> expr; + + AnonConst *clone_expr_with_block_impl () const override + { + return new AnonConst (*this); + } +}; + +class ConstBlock : public ExprWithBlock +{ +public: + ConstBlock (AnonConst &&expr, location_t locus = UNKNOWN_LOCATION, + std::vector<Attribute> &&outer_attrs = {}) + : ExprWithBlock (), expr (std::move (expr)), + outer_attrs (std::move (outer_attrs)), locus (locus) + {} + + ConstBlock (const ConstBlock &other) + : ExprWithBlock (other), expr (other.expr), outer_attrs (other.outer_attrs), + locus (other.locus) + {} + + ConstBlock operator= (const ConstBlock &other) + { + expr = other.expr; + node_id = other.node_id; + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + std::string as_string () const override; + + Expr::Kind get_expr_kind () const override { return Expr::Kind::ConstBlock; } + + AnonConst &get_const_expr () { return expr; } + + void accept_vis (ASTVisitor &vis) override; + + std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + location_t get_locus () const override { return locus; } + + bool is_marked_for_strip () const override { return marked_for_strip; } + void mark_for_strip () override { marked_for_strip = true; } + +private: + AnonConst expr; + + std::vector<Attribute> outer_attrs; + location_t locus; + bool marked_for_strip = false; + + ConstBlock *clone_expr_with_block_impl () const override + { + return new ConstBlock (*this); + } +}; + // Represents a type-specified closure expression AST node class ClosureExprInnerTyped : public ClosureExpr { @@ -2761,7 +2964,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? @@ -2771,11 +2974,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) {} @@ -2796,7 +2999,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 @@ -2812,7 +3021,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; @@ -2823,14 +3032,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) @@ -2892,7 +3102,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 @@ -2908,6 +3124,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) {} @@ -2917,15 +3137,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 @@ -3310,6 +3528,81 @@ protected: } }; +class BoxExpr : public ExprWithoutBlock +{ + std::unique_ptr<Expr> expr; + std::vector<Attribute> outer_attrs; + location_t locus; + +public: + BoxExpr (std::unique_ptr<Expr> expr, std::vector<Attribute> outer_attrs, + location_t locus) + : expr (std::move (expr)), outer_attrs (outer_attrs), locus (locus) + {} + + // Copy constructor with clone + BoxExpr (BoxExpr const &other) + : ExprWithoutBlock (other), outer_attrs (other.outer_attrs), + locus (other.locus) + { + // guard to protect from null pointer dereference + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + } + + BoxExpr &operator= (BoxExpr const &other) + { + ExprWithoutBlock::operator= (other); + locus = other.locus; + outer_attrs = other.outer_attrs; + + // guard to protect from null pointer dereference + if (other.expr != nullptr) + expr = other.expr->clone_expr (); + else + expr = nullptr; + + return *this; + } + + // move constructors + BoxExpr (BoxExpr &&other) = default; + BoxExpr &operator= (BoxExpr &&other) = default; + + location_t get_locus () const override final { return locus; } + + void accept_vis (ASTVisitor &vis) override; + + void mark_for_strip () override { expr = nullptr; } + bool is_marked_for_strip () const override { return expr == nullptr; } + + const std::vector<Attribute> &get_outer_attrs () const { return outer_attrs; } + std::vector<Attribute> &get_outer_attrs () override { return outer_attrs; } + + void set_outer_attrs (std::vector<Attribute> new_attrs) override + { + outer_attrs = std::move (new_attrs); + } + + std::string as_string () const override; + + Expr &get_boxed_expr () + { + rust_assert (expr != nullptr); + 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 */ + BoxExpr *clone_expr_without_block_impl () const override + { + return new BoxExpr (*this); + } +}; + // Return expression AST node representation class ReturnExpr : public ExprWithoutBlock { @@ -3388,6 +3681,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 */ @@ -3470,6 +3765,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 */ @@ -3485,7 +3782,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: @@ -3494,7 +3791,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)), @@ -3534,9 +3831,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; } @@ -3558,6 +3856,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 @@ -3568,7 +3878,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)) @@ -3576,6 +3886,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 */ @@ -3596,7 +3911,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), @@ -3634,6 +3949,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 */ @@ -3657,7 +3977,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), @@ -3717,6 +4037,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 */ @@ -3739,7 +4064,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)), @@ -3786,6 +4111,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 */ @@ -3909,6 +4239,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); } @@ -4103,6 +4435,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) */ @@ -4298,7 +4632,7 @@ private: public: MatchCase (MatchArm arm, std::unique_ptr<Expr> expr) : arm (std::move (arm)), expr (std::move (expr)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} MatchCase (const MatchCase &other) @@ -4432,6 +4766,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 */ @@ -4511,6 +4847,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 */ @@ -4593,6 +4931,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 */ @@ -4603,7 +4943,7 @@ protected: }; // Inline-assembly specific options -enum class InlineAsmOptions +enum class InlineAsmOption { PURE = 1 << 0, NOMEM = 1 << 1, @@ -4616,12 +4956,6 @@ enum class InlineAsmOptions MAY_UNWIND = 1 << 8, }; -struct AnonConst -{ - NodeId id; - std::unique_ptr<Expr> value; -}; - struct InlineAsmRegOrRegClass { enum Type @@ -4640,13 +4974,39 @@ struct InlineAsmRegOrRegClass std::string Symbol; }; + Type type; + struct Reg reg; + struct RegClass reg_class; + Identifier name; location_t locus; }; -struct InlineAsmOperand +struct LlvmOperand { - enum RegisterType + 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: + enum class RegisterType { In, Out, @@ -4654,46 +5014,339 @@ struct InlineAsmOperand SplitInOut, Const, Sym, + Label, + }; + + class Register + { + public: + Register () {} + virtual ~Register () = default; + + std::unique_ptr<Register> clone () const + { + return std::unique_ptr<Register> (clone_impl ()); + } + + protected: + virtual Register *clone_impl () const = 0; }; - struct In + class In : public Register { - InlineAsmRegOrRegClass reg; + public: + tl::optional<InlineAsmRegOrRegClass> reg; std::unique_ptr<Expr> expr; + + In (tl::optional<struct InlineAsmRegOrRegClass> ®, + std::unique_ptr<Expr> expr) + : reg (reg), expr (std::move (expr)) + { + rust_assert (this->expr != nullptr); + } + + In (const In &other) + { + reg = other.reg; + + expr = other.expr->clone_expr (); + } + + In operator= (const In &other) + { + reg = other.reg; + expr = other.expr->clone_expr (); + + return *this; + } + + private: + In *clone_impl () const { return new In (*this); } }; - struct Out + class Out : public Register { - InlineAsmRegOrRegClass reg; + public: + tl::optional<InlineAsmRegOrRegClass> reg; bool late; std::unique_ptr<Expr> expr; // can be null + + Out (tl::optional<struct InlineAsmRegOrRegClass> ®, bool late, + std::unique_ptr<Expr> expr) + : reg (reg), late (late), expr (std::move (expr)) + { + rust_assert (this->expr != nullptr); + } + + Out (const Out &other) + { + reg = other.reg; + late = other.late; + expr = other.expr->clone_expr (); + } + + Out operator= (const Out &other) + { + reg = other.reg; + late = other.late; + expr = other.expr->clone_expr (); + return *this; + } + + private: + Out *clone_impl () const { return new Out (*this); } }; - struct InOut + class InOut : public Register { - InlineAsmRegOrRegClass reg; + public: + tl::optional<InlineAsmRegOrRegClass> reg; bool late; std::unique_ptr<Expr> expr; // this can't be null + + InOut (tl::optional<struct InlineAsmRegOrRegClass> ®, bool late, + std::unique_ptr<Expr> expr) + : reg (reg), late (late), expr (std::move (expr)) + { + rust_assert (this->expr != nullptr); + } + + InOut (const InOut &other) + { + reg = other.reg; + late = other.late; + expr = other.expr->clone_expr (); + } + + InOut operator= (const InOut &other) + { + reg = other.reg; + late = other.late; + expr = other.expr->clone_expr (); + + return *this; + } + + private: + InOut *clone_impl () const { return new InOut (*this); } }; - struct SplitInOut + class SplitInOut : public Register { - InlineAsmRegOrRegClass reg; + public: + tl::optional<InlineAsmRegOrRegClass> reg; bool late; std::unique_ptr<Expr> in_expr; std::unique_ptr<Expr> out_expr; // could be null + + SplitInOut (tl::optional<struct InlineAsmRegOrRegClass> ®, bool late, + std::unique_ptr<Expr> in_expr, std::unique_ptr<Expr> out_expr) + : reg (reg), late (late), in_expr (std::move (in_expr)), + out_expr (std::move (out_expr)) + { + rust_assert (this->in_expr != nullptr); + rust_assert (this->out_expr != nullptr); + } + + SplitInOut (const SplitInOut &other) + { + reg = other.reg; + late = other.late; + in_expr = other.in_expr->clone_expr (); + out_expr = other.out_expr->clone_expr (); + } + + SplitInOut operator= (const SplitInOut &other) + { + reg = other.reg; + late = other.late; + in_expr = other.in_expr->clone_expr (); + out_expr = other.out_expr->clone_expr (); + + return *this; + } + + private: + SplitInOut *clone_impl () const { return new SplitInOut (*this); } }; - struct Const + class Const : public Register { + public: AnonConst anon_const; + + private: + Const *clone_impl () const { return new Const (*this); } + }; + + class Sym : public Register + { + public: + std::unique_ptr<Expr> expr; + + Sym (std::unique_ptr<Expr> expr) : expr (std::move (expr)) + { + rust_assert (this->expr != nullptr); + } + Sym (const Sym &other) + { + expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); + } + + Sym operator= (const Sym &other) + { + expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); + return *this; + } + + private: + Sym *clone_impl () const { return new Sym (*this); } }; - struct Sym + class Label : public Register { - std::unique_ptr<Expr> sym; + public: + std::string label_name; + std::unique_ptr<Expr> expr; + + Label (tl::optional<std::string> label_name, std::unique_ptr<Expr> expr) + : expr (std::move (expr)) + { + rust_assert (this->expr != nullptr); + if (label_name.has_value ()) + this->label_name = label_name.value (); + } + Label (const Label &other) + { + expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); + } + + Label operator= (const Label &other) + { + expr = std::unique_ptr<Expr> (other.expr->clone_expr ()); + return *this; + } + + private: + Label *clone_impl () const { return new Label (*this); } }; + + InlineAsmOperand (const InlineAsmOperand &other) + : register_type (other.register_type), locus (other.locus), + reg (other.reg->clone ()) + {} + + InlineAsmOperand (const In ®, location_t locus) + : register_type (RegisterType::In), locus (locus), reg (new In (reg)) + {} + InlineAsmOperand (const Out ®, location_t locus) + : register_type (RegisterType::Out), locus (locus), reg (new Out (reg)) + {} + InlineAsmOperand (const InOut ®, location_t locus) + : register_type (RegisterType::InOut), locus (locus), reg (new InOut (reg)) + {} + InlineAsmOperand (const SplitInOut ®, location_t locus) + : register_type (RegisterType::SplitInOut), locus (locus), + reg (new SplitInOut (reg)) + {} + InlineAsmOperand (const Const ®, location_t locus) + : register_type (RegisterType::Const), locus (locus), reg (new Const (reg)) + {} + InlineAsmOperand (const Sym ®, location_t locus) + : register_type (RegisterType::Sym), locus (locus), reg (new Sym (reg)) + {} + InlineAsmOperand (const Label ®, location_t locus) + : register_type (RegisterType::Label), locus (locus), reg (new Label (reg)) + {} + + location_t get_locus () const { return locus; } + RegisterType get_register_type () const { return register_type; } + + // Potentially fail immediately if you don't use get_register_type() to + // inspect the RegisterType first before calling the following functions Check + // first + In &get_in () + { + rust_assert (register_type == RegisterType::In); + return static_cast<In &> (*reg); + } + const In &get_in () const + { + rust_assert (register_type == RegisterType::In); + return static_cast<const In &> (*reg); + } + + Out &get_out () + { + rust_assert (register_type == RegisterType::Out); + return static_cast<Out &> (*reg); + } + const Out &get_out () const + { + rust_assert (register_type == RegisterType::Out); + return static_cast<const Out &> (*reg); + } + + InOut &get_in_out () + { + rust_assert (register_type == RegisterType::InOut); + return static_cast<InOut &> (*reg); + } + const InOut &get_in_out () const + { + rust_assert (register_type == RegisterType::InOut); + return static_cast<const InOut &> (*reg); + } + + SplitInOut &get_split_in_out () + { + rust_assert (register_type == RegisterType::SplitInOut); + return static_cast<SplitInOut &> (*reg); + } + const SplitInOut &get_split_in_out () const + { + rust_assert (register_type == RegisterType::SplitInOut); + return static_cast<const SplitInOut &> (*reg); + } + + Const &get_const () + { + rust_assert (register_type == RegisterType::Const); + return static_cast<Const &> (*reg); + } + const Const &get_const () const + { + rust_assert (register_type == RegisterType::Const); + return static_cast<Const &> (*reg); + } + + Sym &get_sym () + { + rust_assert (register_type == RegisterType::Sym); + return static_cast<Sym &> (*reg); + } + const Sym &get_sym () const + { + rust_assert (register_type == RegisterType::Sym); + return static_cast<const Sym &> (*reg); + } + + Label &get_label () + { + rust_assert (register_type == RegisterType::Label); + return static_cast<Label &> (*reg); + } + const Label &get_label () const + { + rust_assert (register_type == RegisterType::Label); + return static_cast<const Label &> (*reg); + } + +private: + RegisterType register_type; + location_t locus; + std::unique_ptr<Register> reg; }; struct InlineAsmPlaceHolder @@ -4706,11 +5359,8 @@ struct InlineAsmPlaceHolder struct InlineAsmTemplatePiece { bool is_placeholder; - union - { - std::string string; - InlineAsmPlaceHolder placeholder; - }; + std::string string; + InlineAsmPlaceHolder placeholder; }; struct TupleClobber @@ -4723,21 +5373,192 @@ struct TupleClobber struct TupleTemplateStr { // as gccrs still doesn't contain a symbol class I have put them as strings - std::string symbol; - std::string optional_symbol; location_t loc; + std::string symbol; + + location_t get_locus () { return loc; } + TupleTemplateStr (location_t loc, const std::string &symbol) + : loc (loc), symbol (symbol) + {} }; // Inline Assembly Node class InlineAsm : public ExprWithoutBlock { public: + enum class Option + { + PURE = 1 << 0, + NOMEM = 1 << 1, + READONLY = 1 << 2, + PRESERVES_FLAGS = 1 << 3, + NORETURN = 1 << 4, + NOSTACK = 1 << 5, + ATT_SYNTAX = 1 << 6, + RAW = 1 << 7, + MAY_UNWIND = 1 << 8, + }; + +private: + location_t locus; + // TODO: Not sure how outer_attrs plays with InlineAsm, I put it here in order + // to override, very hacky. + std::vector<Attribute> outer_attrs; + +public: + // https://github.com/rust-lang/rust/blob/55cac26a9ef17da1c9c77c0816e88e178b7cc5dd/compiler/rustc_builtin_macros/src/asm.rs#L56C1-L64C7 + // let mut args = AsmArgs { + // templates: vec![first_template], + // operands: vec![], + // named_args: Default::default(), + // reg_args: Default::default(), + // clobber_abis: Vec::new(), + // options: ast::InlineAsmOptions::empty(), + // options_spans: vec![], + // }; std::vector<InlineAsmTemplatePiece> template_; std::vector<TupleTemplateStr> template_strs; std::vector<InlineAsmOperand> operands; - TupleClobber clobber_abi; - InlineAsmOptions options; + std::map<std::string, int> named_args; + std::set<int> reg_args; + std::vector<TupleClobber> clobber_abi; + std::set<InlineAsm::Option> options; + std::vector<location_t> line_spans; + + bool is_global_asm; + + InlineAsm (location_t locus, bool is_global_asm) + : locus (locus), is_global_asm (is_global_asm) + {} + + void accept_vis (ASTVisitor &vis) override; + std::string as_string () const override { return "InlineAsm AST Node"; } + + 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 set_outer_attrs (std::vector<Attribute> v) override { outer_attrs = v; } + + std::vector<InlineAsmTemplatePiece> get_template_ () { return template_; } + + std::vector<TupleTemplateStr> get_template_strs () { return template_strs; } + + std::vector<InlineAsmOperand> get_operands () { return operands; } + + std::vector<TupleClobber> get_clobber_abi () { return clobber_abi; } + + std::set<InlineAsm::Option> get_options () { return options; } + + InlineAsm *clone_expr_without_block_impl () const override + { + return new InlineAsm (*this); + } + + Expr::Kind get_expr_kind () const override { return Expr::Kind::InlineAsm; } + + static std::string option_to_string (Option option) + { + switch (option) + { + case Option::PURE: + return "pure"; + case Option::NOMEM: + return "nomem"; + case Option::READONLY: + return "readonly"; + case Option::PRESERVES_FLAGS: + return "preserves_flags"; + case Option::NORETURN: + return "noreturn"; + case Option::NOSTACK: + return "nostack"; + case Option::ATT_SYNTAX: + return "att_syntax"; + case Option::RAW: + return "raw"; + case Option::MAY_UNWIND: + return "may_unwind"; + default: + rust_unreachable (); + } + } +}; + +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-fmt.cc b/gcc/rust/ast/rust-fmt.cc index a48e8f5..c739943 100644 --- a/gcc/rust/ast/rust-fmt.cc +++ b/gcc/rust/ast/rust-fmt.cc @@ -29,9 +29,11 @@ ffi::RustHamster::to_string () const } Pieces -Pieces::collect (const std::string &to_parse, bool append_newline) +Pieces::collect (const std::string &to_parse, bool append_newline, + ffi::ParseMode parse_mode) { - auto handle = ffi::collect_pieces (to_parse.c_str (), append_newline); + auto handle + = ffi::collect_pieces (to_parse.c_str (), append_newline, parse_mode); // this performs multiple copies, can we avoid them maybe? // TODO: Instead of just creating a vec of, basically, `ffi::Piece`s, we diff --git a/gcc/rust/ast/rust-fmt.h b/gcc/rust/ast/rust-fmt.h index 6a0c116..fa0f5ec 100644 --- a/gcc/rust/ast/rust-fmt.h +++ b/gcc/rust/ast/rust-fmt.h @@ -20,7 +20,6 @@ #define RUST_FMT_H #include "rust-system.h" -#include <cstddef> // FIXME: How to encode Option? @@ -259,10 +258,16 @@ struct FormatArgsHandle RustString rust_string; }; +enum ParseMode +{ + Format = 0, + InlineAsm, +}; + extern "C" { FormatArgsHandle -collect_pieces (const char *input, bool append_newline); +collect_pieces (const char *input, bool append_newline, ParseMode parse_mode); FormatArgsHandle clone_pieces (const FormatArgsHandle &); @@ -275,7 +280,8 @@ void destroy_pieces (FormatArgsHandle); struct Pieces { - static Pieces collect (const std::string &to_parse, bool append_newline); + static Pieces collect (const std::string &to_parse, bool append_newline, + ffi::ParseMode parse_mode); ~Pieces (); Pieces (const Pieces &other); diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index c03de9b..2f53f8d 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -51,21 +51,12 @@ class TypePath; // A type generic parameter (as opposed to a lifetime generic parameter) class TypeParam : public GenericParam { - // bool has_outer_attribute; - // std::unique_ptr<Attribute> outer_attr; - Attribute outer_attr; - + AST::AttrVec outer_attrs; Identifier type_representation; - - // bool has_type_param_bounds; - // TypeParamBounds type_param_bounds; - std::vector<std::unique_ptr<TypeParamBound>> - type_param_bounds; // inlined form - - // bool has_type; + std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds; std::unique_ptr<Type> type; - location_t locus; + bool was_impl_trait; public: Identifier get_type_representation () const { return type_representation; } @@ -77,26 +68,27 @@ public: bool has_type_param_bounds () const { return !type_param_bounds.empty (); } // Returns whether the type param has an outer attribute. - bool has_outer_attribute () const { return !outer_attr.is_empty (); } + bool has_outer_attribute () const { return !outer_attrs.empty (); } - Attribute &get_outer_attribute () { return outer_attr; } + AST::AttrVec &get_outer_attrs () { return outer_attrs; } TypeParam (Identifier type_representation, location_t locus = UNDEF_LOCATION, std::vector<std::unique_ptr<TypeParamBound>> type_param_bounds = std::vector<std::unique_ptr<TypeParamBound>> (), std::unique_ptr<Type> type = nullptr, - Attribute outer_attr = Attribute::create_empty ()) - : GenericParam (Analysis::Mappings::get ()->get_next_node_id ()), - outer_attr (std::move (outer_attr)), + AST::AttrVec outer_attrs = {}, bool was_impl_trait = false) + : GenericParam (Analysis::Mappings::get ().get_next_node_id ()), + outer_attrs (std::move (outer_attrs)), type_representation (std::move (type_representation)), type_param_bounds (std::move (type_param_bounds)), - type (std::move (type)), locus (locus) + type (std::move (type)), locus (locus), was_impl_trait (was_impl_trait) {} // Copy constructor uses clone TypeParam (TypeParam const &other) - : GenericParam (other.node_id), outer_attr (other.outer_attr), - type_representation (other.type_representation), locus (other.locus) + : GenericParam (other.node_id), outer_attrs (other.outer_attrs), + type_representation (other.type_representation), locus (other.locus), + was_impl_trait (other.was_impl_trait) { // guard to prevent null pointer dereference if (other.type != nullptr) @@ -111,9 +103,10 @@ public: TypeParam &operator= (TypeParam const &other) { type_representation = other.type_representation; - outer_attr = other.outer_attr; + outer_attrs = other.outer_attrs; locus = other.locus; node_id = other.node_id; + was_impl_trait = other.was_impl_trait; // guard to prevent null pointer dereference if (other.type != nullptr) @@ -153,17 +146,19 @@ public: return type; } - // TODO: mutable getter seems kinda dodgy std::vector<std::unique_ptr<TypeParamBound>> &get_type_param_bounds () { return type_param_bounds; } + const std::vector<std::unique_ptr<TypeParamBound>> & get_type_param_bounds () const { return type_param_bounds; } + bool from_impl_trait () const { return was_impl_trait; } + protected: // Clone function implementation as virtual method TypeParam *clone_generic_param_impl () const override @@ -210,7 +205,7 @@ public: location_t locus) : lifetime (std::move (lifetime)), lifetime_bounds (std::move (lifetime_bounds)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} std::string as_string () const override; @@ -258,7 +253,7 @@ public: : for_lifetimes (std::move (for_lifetimes)), bound_type (std::move (bound_type)), type_param_bounds (std::move (type_param_bounds)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) + node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus) {} // Copy constructor requires clone @@ -339,7 +334,7 @@ class WhereClause public: WhereClause (std::vector<std::unique_ptr<WhereClauseItem>> where_clause_items) : where_clause_items (std::move (where_clause_items)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // copy constructor with vector clone @@ -396,7 +391,7 @@ class Param : public Visitable public: Param (std::vector<Attribute> outer_attrs, location_t locus) : outer_attrs (std::move (outer_attrs)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} virtual ~Param () = default; @@ -434,13 +429,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 +449,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 +468,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 +518,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 +754,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 +893,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 +956,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 */ @@ -1018,7 +1016,7 @@ protected: virtual UseTree *clone_use_tree_impl () const = 0; UseTree (location_t locus) - : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) + : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} }; @@ -1213,7 +1211,7 @@ public: std::string as_string () const override; - NewBindType get_new_bind_type () { return bind_type; } + NewBindType get_new_bind_type () const { return bind_type; } void accept_vis (ASTVisitor &vis) override; @@ -1301,6 +1299,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 +1326,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 +1351,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 +1360,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 +1370,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 +1464,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 +1597,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 +1658,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, @@ -1718,7 +1729,7 @@ public: std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), field_name (std::move (field_name)), field_type (std::move (field_type)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) + node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus) {} // Copy constructor @@ -1878,7 +1889,7 @@ public: std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), field_type (std::move (field_type)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) + node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus) {} // Copy constructor with clone @@ -1994,6 +2005,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 +2048,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 +2069,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 +2093,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 +2135,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 +2193,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 +2334,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 +2435,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 +2558,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 +2684,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 +2907,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 +2947,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 +2957,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 +2979,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 +3047,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 +3123,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 +3273,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 +3322,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 +3595,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 +3687,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 507e595..575cd23 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: @@ -482,7 +482,7 @@ private: * should make use of the actual rules. If the macro is builtin, then another * associated transcriber should be used */ - static Fragment dummy_builtin (location_t, MacroInvocData &) + static Fragment dummy_builtin (location_t, MacroInvocData &, AST::InvocKind) { rust_unreachable (); return Fragment::create_error (); @@ -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; } @@ -720,7 +710,7 @@ private: location_t locus, bool is_semi_coloned, std::vector<std::unique_ptr<MacroInvocation>> &&pending_eager_invocs) : TraitItem (locus), outer_attrs (std::move (outer_attrs)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()), + node_id (Analysis::Mappings::get ().get_next_node_id ()), invoc_data (std::move (invoc_data)), is_semi_coloned (is_semi_coloned), kind (kind), builtin_kind (builtin_kind), pending_eager_invocs (std::move (pending_eager_invocs)) @@ -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 9131962..ef61d57 100644 --- a/gcc/rust/ast/rust-path.cc +++ b/gcc/rust/ast/rust-path.cc @@ -17,6 +17,7 @@ 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-path.h" #include "rust-system.h" #include "rust-ast-full.h" #include "rust-diagnostics.h" @@ -118,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; } @@ -135,8 +136,11 @@ PathExprSegment::as_string () const } std::string -PathPattern::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,8 +153,10 @@ PathPattern::as_string () const } SimplePath -PathPattern::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 (); @@ -197,7 +203,7 @@ PathInExpression::as_string () const if (has_opening_scope_resolution) str = "::"; - return str + PathPattern::as_string (); + return str + Path::as_string (); } std::string @@ -260,6 +266,27 @@ TypePath::as_simple_path () const locus); } +std::string +TypePath::make_debug_string () const +{ + rust_assert (!segments.empty ()); + + std::string output; + + for (const auto &segment : segments) + { + if (segment != nullptr && !segment->is_lang_item () + && !segment->is_error ()) + { + if (!output.empty () || has_opening_scope_resolution_op ()) + output.append ("::"); + output.append (segment->get_ident_segment ().as_string ()); + } + } + + return output; +} + // hopefully definition here will prevent circular dependency issue TraitBound * TypePath::to_trait_bound (bool in_parens) const @@ -297,7 +324,7 @@ TypePathFunction::as_string () const std::string QualifiedPathInExpression::as_string () const { - return path_type.as_string () + "::" + PathPattern::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 83412eb..6f53188 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -21,7 +21,11 @@ /* "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" +#include "rust-system.h" #include "system.h" namespace Rust { @@ -52,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 @@ -157,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 (); @@ -212,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; } @@ -229,8 +231,6 @@ public: break; case Kind::Either: break; - case Kind::Error: - rust_unreachable (); } } @@ -273,8 +273,6 @@ public: { switch (get_kind ()) { - case Kind::Error: - rust_unreachable (); case Kind::Either: return "Ambiguous: " + path.as_string (); case Kind::Const: @@ -345,32 +343,32 @@ class ConstGenericParam : public GenericParam /** * Default value for the const generic parameter */ - GenericArg default_value; + tl::optional<GenericArg> default_value; - Attribute outer_attr; + AST::AttrVec outer_attrs; location_t locus; public: ConstGenericParam (Identifier name, std::unique_ptr<AST::Type> type, - GenericArg default_value, Attribute outer_attr, - 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_attr (outer_attr), + default_value (std::move (default_value)), outer_attrs (outer_attrs), locus (locus) {} ConstGenericParam (const ConstGenericParam &other) : GenericParam (), name (other.name), type (other.type->clone_type ()), - default_value (other.default_value), outer_attr (other.outer_attr), + default_value (other.default_value), outer_attrs (other.outer_attrs), locus (other.locus) {} 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; } - Attribute &get_outer_attribute () { return outer_attr; } + AST::AttrVec &get_outer_attrs () { return outer_attrs; } AST::Type &get_type () { @@ -379,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; @@ -476,15 +474,23 @@ public: std::string as_string () const; - // TODO: is this better? Or is a "vis_pattern" better? std::vector<GenericArg> &get_generic_args () { return generic_args; } - // TODO: is this better? Or is a "vis_pattern" better? std::vector<GenericArgsBinding> &get_binding_args () { return binding_args; } + const std::vector<GenericArgsBinding> &get_binding_args () const + { + return binding_args; + } + std::vector<Lifetime> &get_lifetime_args () { return lifetime_args; }; - location_t get_locus () { return locus; } + const std::vector<Lifetime> &get_lifetime_args () const + { + return lifetime_args; + }; + + location_t get_locus () const { return locus; } }; /* A segment of a path in expression, including an identifier aspect and maybe @@ -506,7 +512,7 @@ public: GenericArgs generic_args = GenericArgs::create_empty ()) : segment_name (std::move (segment_name)), generic_args (std::move (generic_args)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} /* Constructor for segment with generic arguments (from segment name and all @@ -519,7 +525,7 @@ public: generic_args (GenericArgs (std::move (lifetime_args), std::move (generic_args), std::move (binding_args))), - locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) + locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Returns whether path expression segment is in an error state. @@ -549,68 +555,102 @@ 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 (); } }; // AST node representing a pattern that involves a "path" - abstract base // class -class PathPattern : public Pattern +class Path : public Pattern { - std::vector<PathExprSegment> segments; +public: + enum class Kind + { + LangItem, + Regular, + }; -protected: - PathPattern (std::vector<PathExprSegment> segments) - : segments (std::move (segments)) + Path (std::vector<PathExprSegment> segments) + : segments (std::move (segments)), lang_item (tl::nullopt), + kind (Kind::Regular) + {} + + 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 (); } + 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; - // Removes all segments of the path. - void remove_all_segments () - { - segments.clear (); - segments.shrink_to_fit (); - } - -public: /* Returns whether the path is a single segment (excluding qualified path * initial as segment). */ - bool is_single_segment () const { return segments.size () == 1; } + bool is_single_segment () const + { + rust_assert (kind == Kind::Regular); + return segments.size () == 1; + } std::string as_string () const override; + bool is_lang_item () const { return kind == Kind::LangItem; } + // TODO: this seems kinda dodgy - std::vector<PathExprSegment> &get_segments () { return segments; } - const std::vector<PathExprSegment> &get_segments () const { return segments; } + 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; + } + + LangItem::Kind get_lang_item () const + { + rust_assert (kind == Kind::LangItem); + return *lang_item; + } 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 PathPattern, public PathExpr +class PathInExpression : public Path, public ExprWithoutBlock { std::vector<Attribute> outer_attrs; bool has_opening_scope_resolution; location_t locus; NodeId _node_id; + bool marked_for_strip; + public: std::string as_string () const override; @@ -618,16 +658,25 @@ public: PathInExpression (std::vector<PathExprSegment> path_segments, std::vector<Attribute> outer_attrs, location_t locus, bool has_opening_scope_resolution = false) - : PathPattern (std::move (path_segments)), - 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 ()) + locus (locus), _node_id (Analysis::Mappings::get ().get_next_node_id ()), + marked_for_strip (false) + {} + + 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) {} // 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. @@ -650,9 +699,8 @@ public: void accept_vis (ASTVisitor &vis) override; - // Invalid if path is empty (error state), so base stripping on that. - void mark_for_strip () override { remove_all_segments (); } - bool is_marked_for_strip () const override { return is_error (); } + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } bool opening_scope_resolution () const { @@ -669,14 +717,17 @@ public: outer_attrs = std::move (new_attrs); } - NodeId get_pattern_node_id () const { return get_node_id (); } - PathExprSegment &get_final_segment () { return get_segments ().back (); } const PathExprSegment &get_final_segment () const { return get_segments ().back (); } + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::PathInExpression; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -711,7 +762,8 @@ public: }; private: - PathIdentSegment ident_segment; + tl::optional<LangItem::Kind> lang_item; + tl::optional<PathIdentSegment> ident_segment; location_t locus; protected: @@ -741,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 ()) + 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 ()) + 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) {} @@ -763,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; @@ -773,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 @@ -793,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 (); } }; @@ -834,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, @@ -870,11 +968,7 @@ public: void accept_vis (ASTVisitor &vis) override; // TODO: is this better? Or is a "vis_pattern" better? - GenericArgs &get_generic_args () - { - rust_assert (has_generic_args ()); - return generic_args; - } + GenericArgs &get_generic_args () { return generic_args; } // Use covariance to override base class method TypePathSegmentGeneric *clone_type_path_segment_impl () const override @@ -891,7 +985,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; @@ -924,8 +1018,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) {} @@ -970,11 +1064,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 () @@ -1038,11 +1132,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: @@ -1067,12 +1160,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), @@ -1110,6 +1211,8 @@ public: std::string as_string () const override; + std::string make_debug_string () const; + /* Converts TypePath to SimplePath if possible (i.e. no generic or function * arguments). Otherwise returns an empty SimplePath. */ SimplePath as_simple_path () const; @@ -1118,15 +1221,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; } @@ -1147,9 +1254,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 @@ -1226,7 +1332,7 @@ public: /* AST node representing a qualified path-in-expression pattern (path that * allows specifying trait functions) */ -class QualifiedPathInExpression : public PathPattern, public PathExpr +class QualifiedPathInExpression : public Path, public ExprWithoutBlock { std::vector<Attribute> outer_attrs; QualifiedPathType path_type; @@ -1240,10 +1346,9 @@ public: std::vector<PathExprSegment> path_segments, std::vector<Attribute> outer_attrs, location_t locus) - : PathPattern (std::move (path_segments)), - outer_attrs (std::move (outer_attrs)), + : 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 ()) + _node_id (Analysis::Mappings::get ().get_next_node_id ()) {} /* TODO: maybe make a shortcut constructor that has QualifiedPathType @@ -1287,6 +1392,11 @@ public: NodeId get_node_id () const override { return _node_id; } + Expr::Kind get_expr_kind () const override + { + return Expr::Kind::QualifiedPathInExpression; + } + protected: /* Use covariance to implement clone function as returning this object * rather than base */ @@ -1316,7 +1426,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: @@ -1331,7 +1441,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)), @@ -1378,7 +1488,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; @@ -1398,11 +1508,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 9091637..c62a4c3 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" @@ -30,6 +29,22 @@ along with GCC; see the file COPYING3. If not see namespace Rust { namespace AST { +RangeKind +tokenid_to_rangekind (TokenId id) +{ + switch (id) + { + case DOT_DOT_EQ: + return RangeKind::INCLUDED; + case ELLIPSIS: + return RangeKind::ELLIPSIS; + case DOT_DOT: + return RangeKind::EXCLUDED; + default: + rust_unreachable (); + } +} + std::string LiteralPattern::as_string () const { @@ -73,10 +88,17 @@ std::string RangePattern::as_string () const { // TODO: maybe rewrite to work with non-linearisable bounds - if (has_ellipsis_syntax) - return lower->as_string () + "..." + upper->as_string (); - else - return lower->as_string () + "..=" + upper->as_string (); + switch (range_kind) + { + case RangeKind::EXCLUDED: + return lower->as_string () + ".." + upper->as_string (); + case RangeKind::INCLUDED: + return lower->as_string () + "..=" + upper->as_string (); + case RangeKind::ELLIPSIS: + return lower->as_string () + "..." + upper->as_string (); + default: + rust_unreachable (); + } } std::string diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index abf6de6..6810732 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -36,13 +36,13 @@ public: // Constructor for a literal pattern LiteralPattern (Literal lit, location_t locus) : lit (std::move (lit)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} LiteralPattern (std::string val, Literal::LitType type, location_t locus, PrimitiveCoreType type_hint) : lit (Literal (std::move (val), type, type_hint)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} location_t get_locus () const override final { return locus; } @@ -90,7 +90,7 @@ public: std::unique_ptr<Pattern> to_bind = nullptr) : Pattern (), variable_ident (std::move (ident)), is_ref (is_ref), is_mut (is_mut), to_bind (std::move (to_bind)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} IdentifierPattern (NodeId node_id, Identifier ident, location_t locus, @@ -175,7 +175,7 @@ public: std::string as_string () const override { return std::string (1, '_'); } WildcardPattern (location_t locus) - : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) + : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} location_t get_locus () const override final { return locus; } @@ -204,7 +204,7 @@ public: std::string as_string () const override { return ".."; } RestPattern (location_t locus) - : locus (locus), node_id (Analysis::Mappings::get ()->get_next_node_id ()) + : locus (locus), node_id (Analysis::Mappings::get ().get_next_node_id ()) {} location_t get_locus () const override final { return locus; } @@ -368,13 +368,22 @@ protected: } }; +enum class RangeKind +{ + INCLUDED, + ELLIPSIS, + EXCLUDED, +}; + +RangeKind +tokenid_to_rangekind (TokenId id); // AST node for matching within a certain range (range pattern) class RangePattern : public Pattern { std::unique_ptr<RangePatternBound> lower; std::unique_ptr<RangePatternBound> upper; - bool has_ellipsis_syntax; + RangeKind range_kind; /* location only stored to avoid a dereference - lower pattern should give * correct location so maybe change in future */ @@ -386,18 +395,18 @@ public: // Constructor RangePattern (std::unique_ptr<RangePatternBound> lower, - std::unique_ptr<RangePatternBound> upper, location_t locus, - bool has_ellipsis_syntax = false) + std::unique_ptr<RangePatternBound> upper, RangeKind range_kind, + location_t locus) : lower (std::move (lower)), upper (std::move (upper)), - has_ellipsis_syntax (has_ellipsis_syntax), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + range_kind (range_kind), locus (locus), + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Copy constructor with clone RangePattern (RangePattern const &other) : lower (other.lower->clone_range_pattern_bound ()), upper (other.upper->clone_range_pattern_bound ()), - has_ellipsis_syntax (other.has_ellipsis_syntax), locus (other.locus), + range_kind (other.range_kind), locus (other.locus), node_id (other.node_id) {} @@ -406,7 +415,7 @@ public: { lower = other.lower->clone_range_pattern_bound (); upper = other.upper->clone_range_pattern_bound (); - has_ellipsis_syntax = other.has_ellipsis_syntax; + range_kind = other.range_kind; locus = other.locus; node_id = other.node_id; @@ -419,11 +428,16 @@ public: location_t get_locus () const override final { return locus; } - bool get_has_ellipsis_syntax () { return has_ellipsis_syntax; } + bool get_has_ellipsis_syntax () const + { + return range_kind == RangeKind::ELLIPSIS; + } + + RangeKind get_range_kind () const { return range_kind; } - bool get_has_lower_bound () { return lower != nullptr; } + bool get_has_lower_bound () const { return lower != nullptr; } - bool get_has_upper_bound () { return upper != nullptr; } + bool get_has_upper_bound () const { return upper != nullptr; } void accept_vis (ASTVisitor &vis) override; @@ -469,7 +483,7 @@ public: bool ref_has_two_amps, location_t locus) : has_two_amps (ref_has_two_amps), is_mut (is_mut_reference), pattern (std::move (pattern)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Copy constructor requires clone @@ -612,7 +626,7 @@ public: std::vector<Attribute> outer_attribs, location_t locus) : StructPatternField (std::move (outer_attribs), locus, - Analysis::Mappings::get ()->get_next_node_id ()), + Analysis::Mappings::get ().get_next_node_id ()), index (index), tuple_pattern (std::move (tuple_pattern)) {} @@ -692,7 +706,7 @@ public: std::vector<Attribute> outer_attrs, location_t locus) : StructPatternField (std::move (outer_attrs), locus, - Analysis::Mappings::get ()->get_next_node_id ()), + Analysis::Mappings::get ().get_next_node_id ()), ident (std::move (ident)), ident_pattern (std::move (ident_pattern)) {} @@ -771,7 +785,7 @@ public: StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut, std::vector<Attribute> outer_attrs, location_t locus) : StructPatternField (std::move (outer_attrs), locus, - Analysis::Mappings::get ()->get_next_node_id ()), + Analysis::Mappings::get ().get_next_node_id ()), has_ref (is_ref), has_mut (is_mut), ident (std::move (ident)) {} @@ -926,7 +940,7 @@ public: StructPatternElements elems = StructPatternElements::create_empty ()) : path (std::move (struct_path)), elems (std::move (elems)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()), locus (locus) + node_id (Analysis::Mappings::get ().get_next_node_id ()), locus (locus) {} /* TODO: constructor to construct via elements included in @@ -1146,7 +1160,7 @@ public: TupleStructPattern (PathInExpression tuple_struct_path, std::unique_ptr<TupleStructItems> items) : path (std::move (tuple_struct_path)), items (std::move (items)), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) { rust_assert (this->items != nullptr); } @@ -1395,7 +1409,7 @@ public: TuplePattern (std::unique_ptr<TuplePatternItems> items, location_t locus) : items (std::move (items)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) { rust_assert (this->items != nullptr); } @@ -1462,7 +1476,7 @@ public: GroupedPattern (std::unique_ptr<Pattern> pattern_in_parens, location_t locus) : pattern_in_parens (std::move (pattern_in_parens)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Copy constructor uses clone @@ -1521,7 +1535,7 @@ public: SlicePattern (std::vector<std::unique_ptr<Pattern>> items, location_t locus) : items (std::move (items)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Copy constructor with vector clone @@ -1588,7 +1602,7 @@ public: AltPattern (std::vector<std::unique_ptr<Pattern>> alts, location_t locus) : alts (std::move (alts)), locus (locus), - node_id (Analysis::Mappings::get ()->get_next_node_id ()) + node_id (Analysis::Mappings::get ().get_next_node_id ()) {} // Copy constructor with vector clone @@ -1643,7 +1657,7 @@ protected: }; // Moved definition to rust-path.h -class PathPattern; +class Path; // Forward decls for paths (defined in rust-path.h) class PathInExpression; diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 51c5918..e64fbe4 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 23572a2..c785b6e 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -48,11 +48,16 @@ public: std::vector<LifetimeParam> &get_for_lifetimes () { return for_lifetimes; } + const std::vector<LifetimeParam> &get_for_lifetimes () const + { + return for_lifetimes; + } + TraitBound (TypePath type_path, location_t locus, bool in_parens = false, bool opening_question_mark = false, std::vector<LifetimeParam> for_lifetimes = std::vector<LifetimeParam> ()) - : TypeParamBound (Analysis::Mappings::get ()->get_next_node_id ()), + : TypeParamBound (Analysis::Mappings::get ().get_next_node_id ()), in_parens (in_parens), opening_question_mark (opening_question_mark), for_lifetimes (std::move (for_lifetimes)), type_path (std::move (type_path)), locus (locus) @@ -68,6 +73,13 @@ public: type_path (std::move (type_path)), locus (locus) {} + TraitBound (TraitBound const &other) + : TypeParamBound (other.get_node_id ()), in_parens (other.in_parens), + opening_question_mark (other.opening_question_mark), + for_lifetimes (other.for_lifetimes), type_path (other.type_path), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } @@ -81,6 +93,11 @@ public: bool is_in_parens () const { return in_parens; } bool has_opening_question_mark () const { return opening_question_mark; } + TypeParamBoundType get_bound_type () const override + { + return TypeParamBound::TypeParamBoundType::TRAIT; + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -295,33 +312,31 @@ public: // Impl trait with a single bound? Poor reference material here. class ImplTraitTypeOneBound : public TypeNoBounds { - TraitBound trait_bound; + std::unique_ptr<TypeParamBound> trait_bound; location_t locus; -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override - { - return new ImplTraitTypeOneBound (*this); - } - public: - ImplTraitTypeOneBound (TraitBound trait_bound, location_t locus) + ImplTraitTypeOneBound (std::unique_ptr<TypeParamBound> trait_bound, + location_t locus) : trait_bound (std::move (trait_bound)), locus (locus) {} + ImplTraitTypeOneBound (ImplTraitTypeOneBound const &other) + : trait_bound (other.trait_bound->clone_type_param_bound ()), + locus (other.locus) + {} + std::string as_string () const override; location_t get_locus () const override final { return locus; } void accept_vis (ASTVisitor &vis) override; - // TODO: would a "vis_type" be better? - TraitBound &get_trait_bound () + std::unique_ptr<TypeParamBound> &get_trait_bound () { return trait_bound; } + + TypeNoBounds *clone_type_no_bounds_impl () const override { - // TODO: check to ensure invariants are met? - return trait_bound; + return new ImplTraitTypeOneBound (*this); } }; @@ -519,6 +534,9 @@ public: return *type; } + // Getter for direct access to the type unique_ptr + std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -532,7 +550,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; @@ -543,11 +561,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) {} @@ -588,10 +607,14 @@ 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; } + // Getter for direct access to the type unique_ptr + std::unique_ptr<TypeNoBounds> &get_type_ptr () { return type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -654,6 +677,11 @@ public: return *size; } + std::unique_ptr<Type> &get_element_type () { return elem_type; } + + // Additional getter for direct access to the size expr unique_ptr + std::unique_ptr<Expr> &get_size_ptr () { return size; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -707,6 +735,9 @@ public: return *elem_type; } + // Getter for direct access to the elem_type unique_ptr + std::unique_ptr<Type> &get_elem_type_ptr () { return elem_type; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ |