diff options
author | Nala Ginrut <mulei@gnu.org> | 2020-04-30 00:22:36 +0800 |
---|---|---|
committer | Philip Herron <philip.herron@embecosm.com> | 2020-11-27 18:07:04 +0000 |
commit | 7266d66d2321562ef74daf90ffb1ad70d081d890 (patch) | |
tree | 89ad46fd0e85eed625eac6ceba9b04d770b0390a | |
parent | 89d78a4a9e0af7e4a7da88c3e6d7688b8423fc39 (diff) | |
download | gcc-7266d66d2321562ef74daf90ffb1ad70d081d890.zip gcc-7266d66d2321562ef74daf90ffb1ad70d081d890.tar.gz gcc-7266d66d2321562ef74daf90ffb1ad70d081d890.tar.bz2 |
Fix indentation
35 files changed, 14451 insertions, 12580 deletions
diff --git a/gcc/rust/ast/clone-test.h b/gcc/rust/ast/clone-test.h index 0c71c82..7d530d2 100644 --- a/gcc/rust/ast/clone-test.h +++ b/gcc/rust/ast/clone-test.h @@ -87,4 +87,4 @@ namespace user_code { } #endif -#endif
\ No newline at end of file +#endif diff --git a/gcc/rust/ast/rust-ast-containers.h b/gcc/rust/ast/rust-ast-containers.h index 81b0187..fa400f1 100644 --- a/gcc/rust/ast/rust-ast-containers.h +++ b/gcc/rust/ast/rust-ast-containers.h @@ -2,47 +2,52 @@ #define RUST_AST_CONTAINERS_H // crappy redefined AST maybe. may move -/* This is mainly the "logical", more "abstract" representation of the code, while the "AST" itself is - * more high-level and matches the language better. */ +/* This is mainly the "logical", more "abstract" representation of the code, + * while the "AST" itself is more high-level and matches the language better. */ // this is now deprecated and replaced with the proper AST #error "rust-ast-containers.h was included by accident. Don't use." namespace Rust { - namespace AST { - struct Module { - public: - }; - - struct Crate { - public: - Module root_module; - }; - - // replace with rust-types.h version - struct AttributeList { - public: - //::std::vector<Attribute> attribs; - }; - - // replace with rust-types.h version - struct Visibility {}; - - /*enum VisibilityType { - Private, - PublicFull, - PublicInPath, - PublicCrate, - PublicSuper, - PublicSelfModule - }; - - // Represents visibility - maybe make into an enum or union or something - struct Visibility { - }; - - */ - } -} - -#endif
\ No newline at end of file +namespace AST { +struct Module +{ +public: +}; + +struct Crate +{ +public: + Module root_module; +}; + +// replace with rust-types.h version +struct AttributeList +{ +public: + //::std::vector<Attribute> attribs; +}; + +// replace with rust-types.h version +struct Visibility +{ +}; + +/*enum VisibilityType { + Private, + PublicFull, + PublicInPath, + PublicCrate, + PublicSuper, + PublicSelfModule +}; + +// Represents visibility - maybe make into an enum or union or something +struct Visibility { +}; + +*/ +} // namespace AST +} // namespace Rust + +#endif diff --git a/gcc/rust/ast/rust-ast-visitor.h b/gcc/rust/ast/rust-ast-visitor.h index b8e92c2..eb680b8 100644 --- a/gcc/rust/ast/rust-ast-visitor.h +++ b/gcc/rust/ast/rust-ast-visitor.h @@ -1,224 +1,226 @@ #ifndef RUST_AST_VISITOR_H #define RUST_AST_VISITOR_H -// Visitor base for AST +// Visitor base for AST // full include not required - only forward decls #include "rust-ast-full-decls.h" namespace Rust { - namespace AST { - // Pure abstract class that provides an interface for accessing different classes of the AST. - class ASTVisitor { - public: - // only concrete class overloads are required +namespace AST { +// Pure abstract class that provides an interface for accessing different +// classes of the AST. +class ASTVisitor +{ +public: + // only concrete class overloads are required - // rust-ast.h - //virtual void visit(AttrInput& attr_input) = 0; - //virtual void visit(TokenTree& token_tree) = 0; - //virtual void visit(MacroMatch& macro_match) = 0; - virtual void visit(Token& tok) = 0; - virtual void visit(DelimTokenTree& delim_tok_tree) = 0; - virtual void visit(AttrInputMetaItemContainer& input) = 0; - //virtual void visit(MetaItem& meta_item) = 0; - //virtual void visit(Stmt& stmt) = 0; - //virtual void visit(Expr& expr) = 0; - virtual void visit(IdentifierExpr& ident_expr) = 0; - //virtual void visit(Pattern& pattern) = 0; - //virtual void visit(Type& type) = 0; - //virtual void visit(TypeParamBound& type_param_bound) = 0; - virtual void visit(Lifetime& lifetime) = 0; - //virtual void visit(GenericParam& generic_param) = 0; - virtual void visit(LifetimeParam& lifetime_param) = 0; - //virtual void visit(TraitItem& trait_item) = 0; - //virtual void visit(InherentImplItem& inherent_impl_item) = 0; - //virtual void visit(TraitImplItem& trait_impl_item) = 0; - virtual void visit(MacroInvocationSemi& macro) = 0; - - // rust-path.h - virtual void visit(PathInExpression& path) = 0; - virtual void visit(TypePathSegment& segment) = 0; - virtual void visit(TypePathSegmentGeneric& segment) = 0; - virtual void visit(TypePathSegmentFunction& segment) = 0; - virtual void visit(TypePath& path) = 0; - virtual void visit(QualifiedPathInExpression& path) = 0; - virtual void visit(QualifiedPathInType& path) = 0; + // rust-ast.h + // virtual void visit(AttrInput& attr_input) = 0; + // virtual void visit(TokenTree& token_tree) = 0; + // virtual void visit(MacroMatch& macro_match) = 0; + virtual void visit (Token &tok) = 0; + virtual void visit (DelimTokenTree &delim_tok_tree) = 0; + virtual void visit (AttrInputMetaItemContainer &input) = 0; + // virtual void visit(MetaItem& meta_item) = 0; + // virtual void visit(Stmt& stmt) = 0; + // virtual void visit(Expr& expr) = 0; + virtual void visit (IdentifierExpr &ident_expr) = 0; + // virtual void visit(Pattern& pattern) = 0; + // virtual void visit(Type& type) = 0; + // virtual void visit(TypeParamBound& type_param_bound) = 0; + virtual void visit (Lifetime &lifetime) = 0; + // virtual void visit(GenericParam& generic_param) = 0; + virtual void visit (LifetimeParam &lifetime_param) = 0; + // virtual void visit(TraitItem& trait_item) = 0; + // virtual void visit(InherentImplItem& inherent_impl_item) = 0; + // virtual void visit(TraitImplItem& trait_impl_item) = 0; + virtual void visit (MacroInvocationSemi ¯o) = 0; - // rust-expr.h - virtual void visit(LiteralExpr& expr) = 0; - virtual void visit(AttrInputLiteral& attr_input) = 0; - virtual void visit(MetaItemLitExpr& meta_item) = 0; - virtual void visit(MetaItemPathLit& meta_item) = 0; - virtual void visit(BorrowExpr& expr) = 0; - virtual void visit(DereferenceExpr& expr) = 0; - virtual void visit(ErrorPropagationExpr& expr) = 0; - virtual void visit(NegationExpr& expr) = 0; - virtual void visit(ArithmeticOrLogicalExpr& expr) = 0; - virtual void visit(ComparisonExpr& expr) = 0; - virtual void visit(LazyBooleanExpr& expr) = 0; - virtual void visit(TypeCastExpr& expr) = 0; - virtual void visit(AssignmentExpr& expr) = 0; - virtual void visit(CompoundAssignmentExpr& expr) = 0; - virtual void visit(GroupedExpr& expr) = 0; - //virtual void visit(ArrayElems& elems) = 0; - virtual void visit(ArrayElemsValues& elems) = 0; - virtual void visit(ArrayElemsCopied& elems) = 0; - virtual void visit(ArrayExpr& expr) = 0; - virtual void visit(ArrayIndexExpr& expr) = 0; - virtual void visit(TupleExpr& expr) = 0; - virtual void visit(TupleIndexExpr& expr) = 0; - virtual void visit(StructExprStruct& expr) = 0; - //virtual void visit(StructExprField& field) = 0; - virtual void visit(StructExprFieldIdentifier& field) = 0; - virtual void visit(StructExprFieldIdentifierValue& field) = 0; - virtual void visit(StructExprFieldIndexValue& field) = 0; - virtual void visit(StructExprStructFields& expr) = 0; - virtual void visit(StructExprStructBase& expr) = 0; - virtual void visit(StructExprTuple& expr) = 0; - virtual void visit(StructExprUnit& expr) = 0; - //virtual void visit(EnumExprField& field) = 0; - virtual void visit(EnumExprFieldIdentifier& field) = 0; - virtual void visit(EnumExprFieldIdentifierValue& field) = 0; - virtual void visit(EnumExprFieldIndexValue& field) = 0; - virtual void visit(EnumExprStruct& expr) = 0; - virtual void visit(EnumExprTuple& expr) = 0; - virtual void visit(EnumExprFieldless& expr) = 0; - virtual void visit(CallExpr& expr) = 0; - virtual void visit(MethodCallExpr& expr) = 0; - virtual void visit(FieldAccessExpr& expr) = 0; - virtual void visit(ClosureExprInner& expr) = 0; - virtual void visit(BlockExpr& expr) = 0; - virtual void visit(ClosureExprInnerTyped& expr) = 0; - virtual void visit(ContinueExpr& expr) = 0; - virtual void visit(BreakExpr& expr) = 0; - virtual void visit(RangeFromToExpr& expr) = 0; - virtual void visit(RangeFromExpr& expr) = 0; - virtual void visit(RangeToExpr& expr) = 0; - virtual void visit(RangeFullExpr& expr) = 0; - virtual void visit(RangeFromToInclExpr& expr) = 0; - virtual void visit(RangeToInclExpr& expr) = 0; - virtual void visit(ReturnExpr& expr) = 0; - virtual void visit(UnsafeBlockExpr& expr) = 0; - virtual void visit(LoopExpr& expr) = 0; - virtual void visit(WhileLoopExpr& expr) = 0; - virtual void visit(WhileLetLoopExpr& expr) = 0; - virtual void visit(ForLoopExpr& expr) = 0; - virtual void visit(IfExpr& expr) = 0; - virtual void visit(IfExprConseqElse& expr) = 0; - virtual void visit(IfExprConseqIf& expr) = 0; - virtual void visit(IfExprConseqIfLet& expr) = 0; - virtual void visit(IfLetExpr& expr) = 0; - virtual void visit(IfLetExprConseqElse& expr) = 0; - virtual void visit(IfLetExprConseqIf& expr) = 0; - virtual void visit(IfLetExprConseqIfLet& expr) = 0; - //virtual void visit(MatchCase& match_case) = 0; - virtual void visit(MatchCaseBlockExpr& match_case) = 0; - virtual void visit(MatchCaseExpr& match_case) = 0; - virtual void visit(MatchExpr& expr) = 0; - virtual void visit(AwaitExpr& expr) = 0; - virtual void visit(AsyncBlockExpr& expr) = 0; + // rust-path.h + virtual void visit (PathInExpression &path) = 0; + virtual void visit (TypePathSegment &segment) = 0; + virtual void visit (TypePathSegmentGeneric &segment) = 0; + virtual void visit (TypePathSegmentFunction &segment) = 0; + virtual void visit (TypePath &path) = 0; + virtual void visit (QualifiedPathInExpression &path) = 0; + virtual void visit (QualifiedPathInType &path) = 0; - // rust-item.h - virtual void visit(TypeParam& param) = 0; - //virtual void visit(WhereClauseItem& item) = 0; - virtual void visit(LifetimeWhereClauseItem& item) = 0; - virtual void visit(TypeBoundWhereClauseItem& item) = 0; - virtual void visit(Method& method) = 0; - virtual void visit(ModuleBodied& module) = 0; - virtual void visit(ModuleNoBody& module) = 0; - virtual void visit(ExternCrate& crate) = 0; - //virtual void visit(UseTree& use_tree) = 0; - virtual void visit(UseTreeGlob& use_tree) = 0; - virtual void visit(UseTreeList& use_tree) = 0; - virtual void visit(UseTreeRebind& use_tree) = 0; - virtual void visit(UseDeclaration& use_decl) = 0; - virtual void visit(Function& function) = 0; - virtual void visit(TypeAlias& type_alias) = 0; - virtual void visit(StructStruct& struct_item) = 0; - virtual void visit(TupleStruct& tuple_struct) = 0; - virtual void visit(EnumItem& item) = 0; - virtual void visit(EnumItemTuple& item) = 0; - virtual void visit(EnumItemStruct& item) = 0; - virtual void visit(EnumItemDiscriminant& item) = 0; - virtual void visit(Enum& enum_item) = 0; - virtual void visit(Union& union_item) = 0; - virtual void visit(ConstantItem& const_item) = 0; - virtual void visit(StaticItem& static_item) = 0; - virtual void visit(TraitItemFunc& item) = 0; - virtual void visit(TraitItemMethod& item) = 0; - virtual void visit(TraitItemConst& item) = 0; - virtual void visit(TraitItemType& item) = 0; - virtual void visit(Trait& trait) = 0; - virtual void visit(InherentImpl& impl) = 0; - virtual void visit(TraitImpl& impl) = 0; - //virtual void visit(ExternalItem& item) = 0; - virtual void visit(ExternalStaticItem& item) = 0; - virtual void visit(ExternalFunctionItem& item) = 0; - virtual void visit(ExternBlock& block) = 0; + // rust-expr.h + virtual void visit (LiteralExpr &expr) = 0; + virtual void visit (AttrInputLiteral &attr_input) = 0; + virtual void visit (MetaItemLitExpr &meta_item) = 0; + virtual void visit (MetaItemPathLit &meta_item) = 0; + virtual void visit (BorrowExpr &expr) = 0; + virtual void visit (DereferenceExpr &expr) = 0; + virtual void visit (ErrorPropagationExpr &expr) = 0; + virtual void visit (NegationExpr &expr) = 0; + virtual void visit (ArithmeticOrLogicalExpr &expr) = 0; + virtual void visit (ComparisonExpr &expr) = 0; + virtual void visit (LazyBooleanExpr &expr) = 0; + virtual void visit (TypeCastExpr &expr) = 0; + virtual void visit (AssignmentExpr &expr) = 0; + virtual void visit (CompoundAssignmentExpr &expr) = 0; + virtual void visit (GroupedExpr &expr) = 0; + // virtual void visit(ArrayElems& elems) = 0; + virtual void visit (ArrayElemsValues &elems) = 0; + virtual void visit (ArrayElemsCopied &elems) = 0; + virtual void visit (ArrayExpr &expr) = 0; + virtual void visit (ArrayIndexExpr &expr) = 0; + virtual void visit (TupleExpr &expr) = 0; + virtual void visit (TupleIndexExpr &expr) = 0; + virtual void visit (StructExprStruct &expr) = 0; + // virtual void visit(StructExprField& field) = 0; + virtual void visit (StructExprFieldIdentifier &field) = 0; + virtual void visit (StructExprFieldIdentifierValue &field) = 0; + virtual void visit (StructExprFieldIndexValue &field) = 0; + virtual void visit (StructExprStructFields &expr) = 0; + virtual void visit (StructExprStructBase &expr) = 0; + virtual void visit (StructExprTuple &expr) = 0; + virtual void visit (StructExprUnit &expr) = 0; + // virtual void visit(EnumExprField& field) = 0; + virtual void visit (EnumExprFieldIdentifier &field) = 0; + virtual void visit (EnumExprFieldIdentifierValue &field) = 0; + virtual void visit (EnumExprFieldIndexValue &field) = 0; + virtual void visit (EnumExprStruct &expr) = 0; + virtual void visit (EnumExprTuple &expr) = 0; + virtual void visit (EnumExprFieldless &expr) = 0; + virtual void visit (CallExpr &expr) = 0; + virtual void visit (MethodCallExpr &expr) = 0; + virtual void visit (FieldAccessExpr &expr) = 0; + virtual void visit (ClosureExprInner &expr) = 0; + virtual void visit (BlockExpr &expr) = 0; + virtual void visit (ClosureExprInnerTyped &expr) = 0; + virtual void visit (ContinueExpr &expr) = 0; + virtual void visit (BreakExpr &expr) = 0; + virtual void visit (RangeFromToExpr &expr) = 0; + virtual void visit (RangeFromExpr &expr) = 0; + virtual void visit (RangeToExpr &expr) = 0; + virtual void visit (RangeFullExpr &expr) = 0; + virtual void visit (RangeFromToInclExpr &expr) = 0; + virtual void visit (RangeToInclExpr &expr) = 0; + virtual void visit (ReturnExpr &expr) = 0; + virtual void visit (UnsafeBlockExpr &expr) = 0; + virtual void visit (LoopExpr &expr) = 0; + virtual void visit (WhileLoopExpr &expr) = 0; + virtual void visit (WhileLetLoopExpr &expr) = 0; + virtual void visit (ForLoopExpr &expr) = 0; + virtual void visit (IfExpr &expr) = 0; + virtual void visit (IfExprConseqElse &expr) = 0; + virtual void visit (IfExprConseqIf &expr) = 0; + virtual void visit (IfExprConseqIfLet &expr) = 0; + virtual void visit (IfLetExpr &expr) = 0; + virtual void visit (IfLetExprConseqElse &expr) = 0; + virtual void visit (IfLetExprConseqIf &expr) = 0; + virtual void visit (IfLetExprConseqIfLet &expr) = 0; + // virtual void visit(MatchCase& match_case) = 0; + virtual void visit (MatchCaseBlockExpr &match_case) = 0; + virtual void visit (MatchCaseExpr &match_case) = 0; + virtual void visit (MatchExpr &expr) = 0; + virtual void visit (AwaitExpr &expr) = 0; + virtual void visit (AsyncBlockExpr &expr) = 0; - // rust-macro.h - virtual void visit(MacroMatchFragment& match) = 0; - virtual void visit(MacroMatchRepetition& match) = 0; - virtual void visit(MacroMatcher& matcher) = 0; - virtual void visit(MacroRulesDefinition& rules_def) = 0; - virtual void visit(MacroInvocation& macro_invoc) = 0; - virtual void visit(MetaItemPath& meta_item) = 0; - virtual void visit(MetaItemSeq& meta_item) = 0; - virtual void visit(MetaWord& meta_item) = 0; - virtual void visit(MetaNameValueStr& meta_item) = 0; - virtual void visit(MetaListPaths& meta_item) = 0; - virtual void visit(MetaListNameValueStr& meta_item) = 0; + // rust-item.h + virtual void visit (TypeParam ¶m) = 0; + // virtual void visit(WhereClauseItem& item) = 0; + virtual void visit (LifetimeWhereClauseItem &item) = 0; + virtual void visit (TypeBoundWhereClauseItem &item) = 0; + virtual void visit (Method &method) = 0; + virtual void visit (ModuleBodied &module) = 0; + virtual void visit (ModuleNoBody &module) = 0; + virtual void visit (ExternCrate &crate) = 0; + // virtual void visit(UseTree& use_tree) = 0; + virtual void visit (UseTreeGlob &use_tree) = 0; + virtual void visit (UseTreeList &use_tree) = 0; + virtual void visit (UseTreeRebind &use_tree) = 0; + virtual void visit (UseDeclaration &use_decl) = 0; + virtual void visit (Function &function) = 0; + virtual void visit (TypeAlias &type_alias) = 0; + virtual void visit (StructStruct &struct_item) = 0; + virtual void visit (TupleStruct &tuple_struct) = 0; + virtual void visit (EnumItem &item) = 0; + virtual void visit (EnumItemTuple &item) = 0; + virtual void visit (EnumItemStruct &item) = 0; + virtual void visit (EnumItemDiscriminant &item) = 0; + virtual void visit (Enum &enum_item) = 0; + virtual void visit (Union &union_item) = 0; + virtual void visit (ConstantItem &const_item) = 0; + virtual void visit (StaticItem &static_item) = 0; + virtual void visit (TraitItemFunc &item) = 0; + virtual void visit (TraitItemMethod &item) = 0; + virtual void visit (TraitItemConst &item) = 0; + virtual void visit (TraitItemType &item) = 0; + virtual void visit (Trait &trait) = 0; + virtual void visit (InherentImpl &impl) = 0; + virtual void visit (TraitImpl &impl) = 0; + // virtual void visit(ExternalItem& item) = 0; + virtual void visit (ExternalStaticItem &item) = 0; + virtual void visit (ExternalFunctionItem &item) = 0; + virtual void visit (ExternBlock &block) = 0; - // rust-pattern.h - virtual void visit(LiteralPattern& pattern) = 0; - virtual void visit(IdentifierPattern& pattern) = 0; - virtual void visit(WildcardPattern& pattern) = 0; - //virtual void visit(RangePatternBound& bound) = 0; - virtual void visit(RangePatternBoundLiteral& bound) = 0; - virtual void visit(RangePatternBoundPath& bound) = 0; - virtual void visit(RangePatternBoundQualPath& bound) = 0; - virtual void visit(RangePattern& pattern) = 0; - virtual void visit(ReferencePattern& pattern) = 0; - //virtual void visit(StructPatternField& field) = 0; - virtual void visit(StructPatternFieldTuplePat& field) = 0; - virtual void visit(StructPatternFieldIdentPat& field) = 0; - virtual void visit(StructPatternFieldIdent& field) = 0; - virtual void visit(StructPattern& pattern) = 0; - //virtual void visit(TupleStructItems& tuple_items) = 0; - virtual void visit(TupleStructItemsNoRange& tuple_items) = 0; - virtual void visit(TupleStructItemsRange& tuple_items) = 0; - virtual void visit(TupleStructPattern& pattern) = 0; - //virtual void visit(TuplePatternItems& tuple_items) = 0; - virtual void visit(TuplePatternItemsMultiple& tuple_items) = 0; - virtual void visit(TuplePatternItemsRanged& tuple_items) = 0; - virtual void visit(TuplePattern& pattern) = 0; - virtual void visit(GroupedPattern& pattern) = 0; - virtual void visit(SlicePattern& pattern) = 0; + // rust-macro.h + virtual void visit (MacroMatchFragment &match) = 0; + virtual void visit (MacroMatchRepetition &match) = 0; + virtual void visit (MacroMatcher &matcher) = 0; + virtual void visit (MacroRulesDefinition &rules_def) = 0; + virtual void visit (MacroInvocation ¯o_invoc) = 0; + virtual void visit (MetaItemPath &meta_item) = 0; + virtual void visit (MetaItemSeq &meta_item) = 0; + virtual void visit (MetaWord &meta_item) = 0; + virtual void visit (MetaNameValueStr &meta_item) = 0; + virtual void visit (MetaListPaths &meta_item) = 0; + virtual void visit (MetaListNameValueStr &meta_item) = 0; - // rust-stmt.h - virtual void visit(EmptyStmt& stmt) = 0; - virtual void visit(LetStmt& stmt) = 0; - virtual void visit(ExprStmtWithoutBlock& stmt) = 0; - virtual void visit(ExprStmtWithBlock& stmt) = 0; - - // rust-type.h - virtual void visit(TraitBound& bound) = 0; - virtual void visit(ImplTraitType& type) = 0; - virtual void visit(TraitObjectType& type) = 0; - virtual void visit(ParenthesisedType& type) = 0; - virtual void visit(ImplTraitTypeOneBound& type) = 0; - virtual void visit(TraitObjectTypeOneBound& type) = 0; - virtual void visit(TupleType& type) = 0; - virtual void visit(NeverType& type) = 0; - virtual void visit(RawPointerType& type) = 0; - virtual void visit(ReferenceType& type) = 0; - virtual void visit(ArrayType& type) = 0; - virtual void visit(SliceType& type) = 0; - virtual void visit(InferredType& type) = 0; - virtual void visit(BareFunctionType& type) = 0; + // rust-pattern.h + virtual void visit (LiteralPattern &pattern) = 0; + virtual void visit (IdentifierPattern &pattern) = 0; + virtual void visit (WildcardPattern &pattern) = 0; + // virtual void visit(RangePatternBound& bound) = 0; + virtual void visit (RangePatternBoundLiteral &bound) = 0; + virtual void visit (RangePatternBoundPath &bound) = 0; + virtual void visit (RangePatternBoundQualPath &bound) = 0; + virtual void visit (RangePattern &pattern) = 0; + virtual void visit (ReferencePattern &pattern) = 0; + // virtual void visit(StructPatternField& field) = 0; + virtual void visit (StructPatternFieldTuplePat &field) = 0; + virtual void visit (StructPatternFieldIdentPat &field) = 0; + virtual void visit (StructPatternFieldIdent &field) = 0; + virtual void visit (StructPattern &pattern) = 0; + // virtual void visit(TupleStructItems& tuple_items) = 0; + virtual void visit (TupleStructItemsNoRange &tuple_items) = 0; + virtual void visit (TupleStructItemsRange &tuple_items) = 0; + virtual void visit (TupleStructPattern &pattern) = 0; + // virtual void visit(TuplePatternItems& tuple_items) = 0; + virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0; + virtual void visit (TuplePatternItemsRanged &tuple_items) = 0; + virtual void visit (TuplePattern &pattern) = 0; + virtual void visit (GroupedPattern &pattern) = 0; + virtual void visit (SlicePattern &pattern) = 0; - // TODO: rust-cond-compilation.h visiting? not currently used - }; - } -} + // rust-stmt.h + virtual void visit (EmptyStmt &stmt) = 0; + virtual void visit (LetStmt &stmt) = 0; + virtual void visit (ExprStmtWithoutBlock &stmt) = 0; + virtual void visit (ExprStmtWithBlock &stmt) = 0; -#endif
\ No newline at end of file + // rust-type.h + virtual void visit (TraitBound &bound) = 0; + virtual void visit (ImplTraitType &type) = 0; + virtual void visit (TraitObjectType &type) = 0; + virtual void visit (ParenthesisedType &type) = 0; + virtual void visit (ImplTraitTypeOneBound &type) = 0; + virtual void visit (TraitObjectTypeOneBound &type) = 0; + virtual void visit (TupleType &type) = 0; + virtual void visit (NeverType &type) = 0; + virtual void visit (RawPointerType &type) = 0; + virtual void visit (ReferenceType &type) = 0; + virtual void visit (ArrayType &type) = 0; + virtual void visit (SliceType &type) = 0; + virtual void visit (InferredType &type) = 0; + virtual void visit (BareFunctionType &type) = 0; + + // TODO: rust-cond-compilation.h visiting? not currently used +}; +} // namespace AST +} // namespace Rust + +#endif diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 54634ef..6a7511e 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -24,1355 +24,1502 @@ #include "rust-location.h" namespace Rust { - // TODO: remove typedefs and make actual types for these - // typedef int Location; - // typedef ::std::string SimplePath; - typedef ::std::string Identifier; - typedef int TupleIndex; - - struct Session; - - namespace AST { - // foward decl: ast visitor - class ASTVisitor; - - // Delimiter types - used in macros and whatever. - enum DelimType { PARENS, SQUARE, CURLY }; - - // Base AST node object - TODO is this really required or useful? Where to draw line? - /*class Node { - public: - // Gets node's Location. - Location get_locus() const { - return loc; - } - - // Sets node's Location. - void set_locus(Location loc_) { - loc = loc_; - } - - // Get node output as a string. Pure virtual. - virtual ::std::string as_string() const = 0; - - virtual ~Node() {} - - // TODO: constructor including Location? Make all derived classes have Location? - - private: - // The node's location. - Location loc; - };*/ - // decided to not have node as a "node" would never need to be stored - - // Attribute body - abstract base class - class AttrInput { - public: - virtual ~AttrInput() {} - - // Unique pointer custom clone function - ::std::unique_ptr<AttrInput> clone_attr_input() const { - return ::std::unique_ptr<AttrInput>(clone_attr_input_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - virtual bool check_cfg_predicate(const Session& session) const = 0; - - // Parse attribute input to meta item, if possible - virtual AttrInput* parse_to_meta_item() const { - return NULL; - } - - protected: - // pure virtual clone implementation - virtual AttrInput* clone_attr_input_impl() const = 0; - }; - - // forward decl for use in token tree method - class Token; - - // A tree of tokens (or a single token) - abstract base class - class TokenTree { - public: - virtual ~TokenTree() {} - - // Unique pointer custom clone function - ::std::unique_ptr<TokenTree> clone_token_tree() const { - return ::std::unique_ptr<TokenTree>(clone_token_tree_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - /* Converts token tree to a flat token stream. Tokens must be pointer to avoid mutual - * dependency with Token. */ - virtual ::std::vector< ::std::unique_ptr<Token> > to_token_stream() const = 0; - - protected: - // pure virtual clone implementation - virtual TokenTree* clone_token_tree_impl() const = 0; - }; - - // Abstract base class for a macro match - class MacroMatch { - public: - virtual ~MacroMatch() {} - - virtual ::std::string as_string() const = 0; - - // Unique pointer custom clone function - ::std::unique_ptr<MacroMatch> clone_macro_match() const { - return ::std::unique_ptr<MacroMatch>(clone_macro_match_impl()); - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual MacroMatch* clone_macro_match_impl() const = 0; - }; - - // A token is a kind of token tree (except delimiter tokens) - class Token - : public TokenTree - , public MacroMatch { - // A token is a kind of token tree (except delimiter tokens) - // A token is a kind of MacroMatch (except $ and delimiter tokens) - // TODO: improve member variables - current ones are the same as lexer token - // Token kind. - TokenId token_id; - // Token location. - Location locus; - // Associated text (if any) of token. - std::string str; - // Token type hint (if any). - PrimitiveCoreType type_hint; - - public: - // Unique pointer custom clone function - ::std::unique_ptr<Token> clone_token() const { - return ::std::unique_ptr<Token>(clone_token_impl()); - } - - // constructor from general text - avoid using if lexer const_TokenPtr is available - Token(TokenId token_id, Location locus, ::std::string str, PrimitiveCoreType type_hint) : - token_id(token_id), locus(locus), str(::std::move(str)), type_hint(type_hint) {} - - // Constructor from lexer const_TokenPtr - /* TODO: find workaround for std::string being NULL - probably have to introduce new - * method in lexer Token, or maybe make conversion method there*/ - Token(const_TokenPtr lexer_token_ptr) : - token_id(lexer_token_ptr->get_id()), locus(lexer_token_ptr->get_locus()), str(""), - type_hint(lexer_token_ptr->get_type_hint()) { - // FIXME: change to "should have str" later? - if (lexer_token_ptr->has_str()) { - str = lexer_token_ptr->get_str(); - - // DEBUG - fprintf(stderr, "ast token created with str '%s'\n", str.c_str()); - } else { - // FIXME: is this returning correct thing? - str = lexer_token_ptr->get_token_description(); - - // DEBUG - fprintf(stderr, "ast token created with string '%s'\n", str.c_str()); - } - - // DEBUG - if (lexer_token_ptr->should_have_str() && !lexer_token_ptr->has_str()) { - fprintf(stderr, "BAD: for token '%s', should have string but does not!\n", - lexer_token_ptr->get_token_description()); - } - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // Return copy of itself but in token stream form. - virtual ::std::vector< ::std::unique_ptr<Token> > to_token_stream() const OVERRIDE; - - TokenId get_id() const { - return token_id; - } - - Location get_locus() const { - return locus; - } - - protected: - // No virtual for now as not polymorphic but can be in future - /*virtual*/ Token* clone_token_impl() const { - return new Token(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual Token* clone_token_tree_impl() const OVERRIDE { - return new Token(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual Token* clone_macro_match_impl() const OVERRIDE { - return new Token(*this); - } - }; - - // A literal - value with a type. Used in LiteralExpr and LiteralPattern. - struct Literal { - public: - enum LitType { - CHAR, - STRING, - RAW_STRING, - BYTE, - BYTE_STRING, - RAW_BYTE_STRING, - INT, - FLOAT, - BOOL - }; - - private: - // TODO: maybe make subclasses of each type of literal with their typed values (or - // generics) - ::std::string value_as_string; - LitType type; - - public: - ::std::string as_string() const { - return value_as_string; - } - - inline LitType get_lit_type() const { - return type; - } - - Literal(::std::string value_as_string, LitType type) : - value_as_string(::std::move(value_as_string)), type(type) {} - - static Literal create_error() { - return Literal("", CHAR); - } - - // Returns whether literal is in an invalid state. - bool is_error() const { - return value_as_string == ""; - } - }; - - // A token tree with delimiters - class DelimTokenTree - : public TokenTree - , public AttrInput { - DelimType delim_type; - ::std::vector< ::std::unique_ptr<TokenTree> > token_trees; - - Location locus; - - // TODO: move all the "parse" functions into a separate class that has the token stream - // reference - will be cleaner Parse a meta item inner. - //::std::unique_ptr<MetaItemInner> parse_meta_item_inner(const ::std::vector< - //::std::unique_ptr<Token> >& token_stream, int& i) const; SimplePath - // parse_simple_path(const ::std::vector< ::std::unique_ptr<Token> >& token_stream, int& - // i) const; SimplePathSegment parse_simple_path_segment(const ::std::vector< - // ::std::unique_ptr<Token> >& token_stream, int& i) const; - //::std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit(const ::std::unique_ptr<Token>& - // tok) const; - //::std::vector< ::std::unique_ptr<MetaItemInner> > parse_meta_item_seq(const - //::std::vector< ::std::unique_ptr<Token> >& token_stream, int& i) const; Literal - // parse_literal(const ::std::unique_ptr<Token>& tok) const; - //::std::unique_ptr<MetaItem> parse_path_meta_item(const ::std::vector< - //::std::unique_ptr<Token> >& token_stream, int& i) const; bool - // is_end_meta_item_tok(TokenId tok) const; - - protected: - // Use covariance to implement clone function as returning a DelimTokenTree object - virtual DelimTokenTree* clone_attr_input_impl() const OVERRIDE { - return new DelimTokenTree(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual DelimTokenTree* clone_token_tree_impl() const OVERRIDE { - return new DelimTokenTree(*this); - } - - public: - DelimTokenTree(DelimType delim_type, - ::std::vector< ::std::unique_ptr<TokenTree> > token_trees - = ::std::vector< ::std::unique_ptr<TokenTree> >(), - Location locus = Location()) : - delim_type(delim_type), - token_trees(::std::move(token_trees)), locus(locus) {} - - // Copy constructor with vector clone - DelimTokenTree(DelimTokenTree const& other) : - delim_type(other.delim_type), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - token_trees.reserve(other.token_trees.size()); - - for (const auto& e : other.token_trees) { - token_trees.push_back(e->clone_token_tree()); - } - } - - // overloaded assignment operator with vector clone - DelimTokenTree& operator=(DelimTokenTree const& other) { - delim_type = other.delim_type; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - token_trees.reserve(other.token_trees.size()); - - for (const auto& e : other.token_trees) { - token_trees.push_back(e->clone_token_tree()); - } - - return *this; - } - - // move constructors - DelimTokenTree(DelimTokenTree&& other) = default; - DelimTokenTree& operator=(DelimTokenTree&& other) = default; - - static DelimTokenTree create_empty() { - return DelimTokenTree(PARENS); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session ATTRIBUTE_UNUSED) const OVERRIDE { - // this should never be called - should be converted first - return false; - } - - virtual AttrInput* parse_to_meta_item() const OVERRIDE; - - virtual ::std::vector< ::std::unique_ptr<Token> > to_token_stream() const OVERRIDE; - }; - - // Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to be defined - class AttrInputLiteral; - - // TODO: move applicable stuff into here or just don't include it because nothing uses it - // A segment of a path (maybe) - class PathSegment { - public: - virtual ~PathSegment() {} - - virtual ::std::string as_string() const = 0; - - // TODO: add visitor here? - }; - - // A segment of a simple path without generic or type arguments - class SimplePathSegment : public PathSegment { - ::std::string segment_name; - Location locus; - - // only allow identifiers, "super", "self", "crate", or "$crate" - public: - // TODO: put checks in constructor to enforce this rule? - SimplePathSegment(::std::string segment_name, Location locus = Location()) : - segment_name(::std::move(segment_name)), locus(locus) {} - - // Returns whether simple path segment is in an invalid state (currently, if empty). - inline bool is_error() const { - return segment_name.empty(); - } - - // Creates an error SimplePathSegment - static SimplePathSegment create_error() { - return SimplePathSegment(::std::string("")); - } - - ::std::string as_string() const; - - inline Location get_locus() const { - return locus; - } - - // TODO: visitor pattern? - }; - - // A simple path without generic or type arguments - class SimplePath { - bool has_opening_scope_resolution; - ::std::vector<SimplePathSegment> segments; - Location locus; - - public: - // Constructor - SimplePath(::std::vector<SimplePathSegment> path_segments, - bool has_opening_scope_resolution = false, Location locus = Location()) : - has_opening_scope_resolution(has_opening_scope_resolution), - segments(::std::move(path_segments)), locus(locus) {} - - // Creates an empty SimplePath. - static SimplePath create_empty() { - return SimplePath(::std::vector<SimplePathSegment>()); - } - - // Returns whether the SimplePath is empty, i.e. has path segments. - inline bool is_empty() const { - return segments.empty(); - } - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - // does this need visitor if not polymorphic? probably not - - // path-to-string comparison operator - bool operator==(const ::std::string& rhs) { - return !has_opening_scope_resolution && segments.size() == 1 - && segments[0].as_string() == rhs; - } - - /* Creates a single-segment SimplePath from a string. This will not check to ensure that - * this is a valid identifier in path, so be careful. Also, this will have no location - * data. - * TODO have checks? */ - static SimplePath from_str(::std::string str) { - ::std::vector<AST::SimplePathSegment> single_segments - = { AST::SimplePathSegment(::std::move(str)) }; - return SimplePath(::std::move(single_segments)); - } - }; - - // aka Attr - // Attribute AST representation - struct Attribute { - private: - SimplePath path; - - // bool has_attr_input; - // AttrInput* attr_input; - ::std::unique_ptr<AttrInput> attr_input; - - Location locus; - - // TODO: maybe a variable storing whether attr input is parsed or not - - public: - // Returns whether Attribute has AttrInput - inline bool has_attr_input() const { - return attr_input != NULL; - } - - // Constructor has pointer AttrInput for polymorphism reasons - Attribute( - SimplePath path, ::std::unique_ptr<AttrInput> input, Location locus = Location()) : - path(::std::move(path)), - attr_input(::std::move(input)), locus(locus) {} - - // Copy constructor must deep copy attr_input as unique pointer - Attribute(Attribute const& other) : path(other.path), locus(other.locus) { - // guard to protect from null pointer dereference - if (other.attr_input != NULL) { - attr_input = other.attr_input->clone_attr_input(); - } - } - - // default destructor - ~Attribute() = default; - - // overload assignment operator to use custom clone method - Attribute& operator=(Attribute const& other) { - path = other.path; - locus = other.locus; - // guard to protect from null pointer dereference - if (other.attr_input != NULL) { - attr_input = other.attr_input->clone_attr_input(); - } - - return *this; - } - - // default move semantics - Attribute(Attribute&& other) = default; - Attribute& operator=(Attribute&& other) = default; - - // Unique pointer custom clone function - ::std::unique_ptr<Attribute> clone_attribute() const { - return ::std::unique_ptr<Attribute>(clone_attribute_impl()); - } - - /*~Attribute() { - delete attr_input; - }*/ - - // Creates an empty attribute (which is invalid) - static Attribute create_empty() { - return Attribute(SimplePath::create_empty(), NULL); - } - - // Returns whether the attribute is considered an "empty" attribute. - inline bool is_empty() const { - return attr_input == NULL && path.is_empty(); - } - - /* e.g.: - #![crate_type = "lib"] - #[test] - #[cfg(target_os = "linux")] - #[allow(non_camel_case_types)] - #![allow(unused_variables)] - */ - - // Full built-in attribute list: - /* cfg - * cfg_attr - * test - * ignore - * should_panic - * derive - * macro_export - * macro_use - * proc_macro - * proc_macro_derive - * proc_macro_attribute - * allow - * warn - * deny - * forbid - * deprecated - * must_use - * link - * link_name - * no_link - * repr - * crate_type - * no_main - * export_name - * link_section - * no_mangle - * used - * crate_name - * inline - * cold - * no_builtins - * target_feature - * doc - * no_std - * no_implicit_prelude - * path - * recursion_limit - * type_length_limit - * panic_handler - * global_allocator - * windows_subsystem - * feature */ - - ::std::string as_string() const; - - // TODO: does this require visitor pattern as not polymorphic? - - // Maybe change to const-reference in future - SimplePath get_path() const { - return path; - } - - // Call to parse attribute body to meta item syntax. - void parse_attr_to_meta_item(); - - // Determines whether cfg predicate is true and item with attribute should not be - // stripped. - bool check_cfg_predicate(const Session& session) { - // assume that cfg predicate actually can exist, i.e. attribute has cfg or cfg_attr - // path - - if (!has_attr_input()) { - return false; - } - - // TODO: maybe replace with storing a "has been parsed" variable? - parse_attr_to_meta_item(); - // can't be const because of this anyway - - return attr_input->check_cfg_predicate(session); - } - - protected: - // not virtual as currently no subclasses of Attribute, but could be in future - /*virtual*/ Attribute* clone_attribute_impl() const { - return new Attribute(*this); - } - }; - - // Forward decl - defined in rust-macro.h - class MetaNameValueStr; - - // abstract base meta item inner class - class MetaItemInner { - protected: - // pure virtual as MetaItemInner - virtual MetaItemInner* clone_meta_item_inner_impl() const = 0; - - public: - // Unique pointer custom clone function - ::std::unique_ptr<MetaItemInner> clone_meta_item_inner() const { - return ::std::unique_ptr<MetaItemInner>(clone_meta_item_inner_impl()); - } - - virtual ~MetaItemInner() {} - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - // HACK: used to simplify parsing - creates a copy of that type, or returns null - virtual MetaNameValueStr* to_meta_name_value_str() const { - return NULL; - } - - // HACK: used to simplify parsing - same thing - virtual SimplePath to_path_item() const { - return SimplePath::create_empty(); - } - - virtual bool check_cfg_predicate(const Session& session) const = 0; - }; - - // Container used to store MetaItems as AttrInput (bridge-ish kinda thing) - class AttrInputMetaItemContainer : public AttrInput { - ::std::vector< ::std::unique_ptr<MetaItemInner> > items; - - public: - AttrInputMetaItemContainer(::std::vector< ::std::unique_ptr<MetaItemInner> > items) : - items(::std::move(items)) {} - - // copy constructor with vector clone - AttrInputMetaItemContainer(const AttrInputMetaItemContainer& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_meta_item_inner()); - } - } - - // no destructor definition required - - // copy assignment operator with vector clone - AttrInputMetaItemContainer& operator=(const AttrInputMetaItemContainer& other) { - AttrInput::operator=(other); - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_meta_item_inner()); - } - - return *this; - } - - // default move constructors - AttrInputMetaItemContainer(AttrInputMetaItemContainer&& other) = default; - AttrInputMetaItemContainer& operator=(AttrInputMetaItemContainer&& other) = default; - - ::std::string as_string() const OVERRIDE; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual AttrInputMetaItemContainer* clone_attr_input_impl() const OVERRIDE { - return new AttrInputMetaItemContainer(*this); - } - }; - - // abstract base meta item class - class MetaItem : public MetaItemInner {}; - - // Forward decl - defined in rust-expr.h - class MetaItemLitExpr; - - // Forward decl - defined in rust-expr.h - class MetaItemPathLit; - - // Forward decl - defined in rust-macro.h - class MetaItemPath; - - // Forward decl - defined in rust-macro.h - class MetaItemSeq; - - // Forward decl - defined in rust-macro.h - class MetaWord; - - // Forward decl - defined in rust-macro.h - class MetaListPaths; - - // Forward decl - defined in rust-macro.h - struct 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: - // Unique pointer custom clone function - ::std::unique_ptr<Stmt> clone_stmt() const { - return ::std::unique_ptr<Stmt>(clone_stmt_impl()); - } - - virtual ~Stmt() {} - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual Stmt* clone_stmt_impl() const = 0; - }; - - // Rust "item" AST node (declaration of top-level/module-level allowed stuff) - class Item : public Stmt { - ::std::vector<Attribute> outer_attrs; - - // TODO: should outer attrs be defined here or in each derived class? - - public: - // Unique pointer custom clone function - ::std::unique_ptr<Item> clone_item() const { - return ::std::unique_ptr<Item>(clone_item_impl()); - } - - ::std::string as_string() const; - - // Adds crate names to the vector passed by reference, if it can (polymorphism). - virtual void add_crate_name(::std::vector< ::std::string>& names ATTRIBUTE_UNUSED) const { - } - - protected: - // Constructor - Item(::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - outer_attrs(::std::move(outer_attribs)) {} - - // Clone function implementation as pure virtual method - virtual Item* clone_item_impl() const = 0; - - /* Save having to specify two clone methods in derived classes by making statement clone - * return item clone. Hopefully won't affect performance too much. */ - virtual Item* clone_stmt_impl() const OVERRIDE { - return clone_item_impl(); - } - }; - - // forward decl of ExprWithoutBlock - class ExprWithoutBlock; - - // Base expression AST node - abstract - class Expr { - // TODO: move outer attribute data to derived classes? - ::std::vector<Attribute> outer_attrs; +// TODO: remove typedefs and make actual types for these +// typedef int Location; +// typedef ::std::string SimplePath; +typedef ::std::string Identifier; +typedef int TupleIndex; + +struct Session; + +namespace AST { +// foward decl: ast visitor +class ASTVisitor; + +// Delimiter types - used in macros and whatever. +enum DelimType +{ + PARENS, + SQUARE, + CURLY +}; + +// Base AST node object - TODO is this really required or useful? Where to draw +// line? +/*class Node { + public: + // Gets node's Location. + Location get_locus() const { + return loc; + } - public: - inline const ::std::vector<Attribute>& get_outer_attrs() const { - return outer_attrs; - } - - // Unique pointer custom clone function - ::std::unique_ptr<Expr> clone_expr() const { - return ::std::unique_ptr<Expr>(clone_expr_impl()); - } - - /* TODO: public methods that could be useful: - * - get_type() - returns type of expression. set_type() may also be useful for some? - * - evaluate() - evaluates expression if constant? can_evaluate()? */ - - // HACK: downcasting without dynamic_cast (if possible) via polymorphism - overrided in - // subclasses of ExprWithoutBlock - virtual ExprWithoutBlock* as_expr_without_block() const { - // DEBUG - fprintf(stderr, "clone expr without block returns null and has not been overriden\n"); - - return NULL; - } - - // TODO: make pure virtual if move out outer attributes to derived classes - virtual ::std::string as_string() const; - - virtual ~Expr() {} - - // HACK: slow way of getting location from base expression through virtual methods. - virtual Location get_locus_slow() const { - return Location(); - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Constructor - Expr(::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - outer_attrs(::std::move(outer_attribs)) {} - - // Clone function implementation as pure virtual method - virtual Expr* clone_expr_impl() const = 0; - - // TODO: think of less hacky way to implement this kind of thing - // Sets outer attributes. - void set_outer_attrs(::std::vector<Attribute> outer_attrs_to_set) { - outer_attrs = ::std::move(outer_attrs_to_set); - } - }; - - // AST node for an expression without an accompanying block - abstract - class ExprWithoutBlock : public Expr { - protected: - // Constructor - ExprWithoutBlock(::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - Expr(::std::move(outer_attribs)) {} - - // pure virtual clone implementation - virtual ExprWithoutBlock* clone_expr_without_block_impl() const = 0; - - /* Save having to specify two clone methods in derived classes by making expr clone - * return exprwithoutblock clone. Hopefully won't affect performance too much. */ - virtual ExprWithoutBlock* clone_expr_impl() const OVERRIDE { - return clone_expr_without_block_impl(); - } - - public: - // Unique pointer custom clone function - ::std::unique_ptr<ExprWithoutBlock> clone_expr_without_block() const { - return ::std::unique_ptr<ExprWithoutBlock>(clone_expr_without_block_impl()); - } - - // downcasting hack from expr to use pratt parsing with parse_expr_without_block - virtual ExprWithoutBlock* as_expr_without_block() const OVERRIDE { - // DEBUG - fprintf(stderr, "about to call the impl for clone expr without block\n"); - - return clone_expr_without_block_impl(); - } - }; - - // HACK: IdentifierExpr, delete when figure out identifier vs expr problem in Pratt parser - // Alternatively, identifiers could just be represented as single-segment paths - class IdentifierExpr : public ExprWithoutBlock { - Identifier ident; - - Location locus; - - public: - IdentifierExpr(Identifier ident, Location locus = Location(), - ::std::vector<Attribute> outer_attrs = ::std::vector<Attribute>()) : - ExprWithoutBlock(::std::move(outer_attrs)), - ident(::std::move(ident)), locus(locus) {} - - ::std::string as_string() const OVERRIDE { - return ident; - } - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone method implementation - virtual IdentifierExpr* clone_expr_without_block_impl() const OVERRIDE { - return new IdentifierExpr(*this); - } - }; - - // Pattern base AST node - class Pattern { - public: - // Unique pointer custom clone function - ::std::unique_ptr<Pattern> clone_pattern() const { - return ::std::unique_ptr<Pattern>(clone_pattern_impl()); - } - - // possible virtual methods: is_refutable() - - virtual ~Pattern() {} - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone pattern implementation as pure virtual method - virtual Pattern* clone_pattern_impl() const = 0; - }; - - // forward decl for Type - class TraitBound; - - // Base class for types as represented in AST - abstract - class Type { - public: - // Unique pointer custom clone function - ::std::unique_ptr<Type> clone_type() const { - return ::std::unique_ptr<Type>(clone_type_impl()); - } - - // virtual destructor - virtual ~Type() {} - - virtual ::std::string as_string() const = 0; - - // HACK: convert to trait bound. Virtual method overriden by classes that enable this. - virtual TraitBound* to_trait_bound(bool in_parens ATTRIBUTE_UNUSED) const { - return NULL; - } - // as pointer, shouldn't require definition beforehand, only forward declaration. - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual Type* clone_type_impl() const = 0; - }; - - // A type without parentheses? - abstract - class TypeNoBounds : public Type { - public: - // Unique pointer custom clone function - ::std::unique_ptr<TypeNoBounds> clone_type_no_bounds() const { - return ::std::unique_ptr<TypeNoBounds>(clone_type_no_bounds_impl()); - } - - protected: - // Clone function implementation as pure virtual method - virtual TypeNoBounds* clone_type_no_bounds_impl() const = 0; - - /* Save having to specify two clone methods in derived classes by making type clone - * return typenobounds clone. Hopefully won't affect performance too much. */ - virtual TypeNoBounds* clone_type_impl() const OVERRIDE { - return clone_type_no_bounds_impl(); - } - }; - - // Abstract base class representing a type param bound - Lifetime and TraitBound extends it - class TypeParamBound { - public: - virtual ~TypeParamBound() {} - - // Unique pointer custom clone function - ::std::unique_ptr<TypeParamBound> clone_type_param_bound() const { - return ::std::unique_ptr<TypeParamBound>(clone_type_param_bound_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual TypeParamBound* clone_type_param_bound_impl() const = 0; - }; - - // Represents a lifetime (and is also a kind of type param bound) - class Lifetime : public TypeParamBound { - public: - enum LifetimeType { - NAMED, // corresponds to LIFETIME_OR_LABEL - STATIC, // corresponds to 'static - WILDCARD // corresponds to '_ - }; - - private: - LifetimeType lifetime_type; - - // TODO: LIFETIME_OR_LABEL (aka lifetime token) is only field - // find way of enclosing token or something - ::std::string lifetime_name; - // only applies for NAMED lifetime_type - - Location locus; - - public: - // Constructor - Lifetime( - LifetimeType type, ::std::string name = ::std::string(), Location locus = Location()) : - lifetime_type(type), - lifetime_name(::std::move(name)), locus(locus) {} - - // Creates an "error" lifetime. - static Lifetime error() { - return Lifetime(NAMED, ::std::string("")); - } - - // Returns true if the lifetime is in an error state. - inline bool is_error() const { - return lifetime_type == NAMED && lifetime_name.empty(); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual Lifetime* clone_type_param_bound_impl() const OVERRIDE { - return new Lifetime(*this); - } - }; - - // Base generic parameter in AST. Abstract - can be represented by a Lifetime or Type param - class GenericParam { - public: - virtual ~GenericParam() {} - - // Unique pointer custom clone function - ::std::unique_ptr<GenericParam> clone_generic_param() const { - return ::std::unique_ptr<GenericParam>(clone_generic_param_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual GenericParam* clone_generic_param_impl() const = 0; - }; - - // A lifetime generic parameter (as opposed to a type generic parameter) - class LifetimeParam : public GenericParam { - Lifetime lifetime; - - // bool has_lifetime_bounds; - // LifetimeBounds lifetime_bounds; - ::std::vector<Lifetime> lifetime_bounds; // inlined LifetimeBounds - - // bool has_outer_attribute; - //::std::unique_ptr<Attribute> outer_attr; - Attribute outer_attr; - - Location locus; - - public: - // Returns whether the lifetime param has any lifetime bounds. - inline bool has_lifetime_bounds() const { - return !lifetime_bounds.empty(); - } - - // Returns whether the lifetime param has an outer attribute. - inline bool has_outer_attribute() const { - return !outer_attr.is_empty(); - } - - // Creates an error state lifetime param. - static LifetimeParam create_error() { - return LifetimeParam(Lifetime::error()); - } - - // Returns whether the lifetime param is in an error state. - inline bool is_error() const { - return lifetime.is_error(); - } - - // Constructor - LifetimeParam(Lifetime lifetime, Location locus = Location(), - ::std::vector<Lifetime> lifetime_bounds = ::std::vector<Lifetime>(), - Attribute outer_attr = Attribute::create_empty()) : - lifetime(::std::move(lifetime)), - lifetime_bounds(::std::move(lifetime_bounds)), outer_attr(::std::move(outer_attr)), - locus(locus) {} - - // TODO: remove copy and assignment operator definitions - not required - - // Copy constructor with clone - LifetimeParam(LifetimeParam const& other) : - lifetime(other.lifetime), lifetime_bounds(other.lifetime_bounds), - outer_attr(other.outer_attr), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone attribute - LifetimeParam& operator=(LifetimeParam const& other) { - lifetime = other.lifetime; - lifetime_bounds = other.lifetime_bounds; - outer_attr = other.outer_attr; - locus = other.locus; - - return *this; - } - - // move constructors - LifetimeParam(LifetimeParam&& other) = default; - LifetimeParam& operator=(LifetimeParam&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LifetimeParam* clone_generic_param_impl() const OVERRIDE { - return new LifetimeParam(*this); - } - }; - - // A macro item AST node - potentially abstract base class - class MacroItem : public Item { - /*public: - ::std::string as_string() const;*/ - protected: - MacroItem(::std::vector<Attribute> outer_attribs) : Item(::std::move(outer_attribs)) {} - }; - - // Item used in trait declarations - abstract base class - class TraitItem { - // bool has_outer_attrs; - // TODO: remove and rely on virtual functions and VisItem-derived attributes? - //::std::vector<Attribute> outer_attrs; - - // NOTE: all children should have outer attributes - - protected: - // Constructor - /*TraitItem(::std::vector<Attribute> outer_attrs = ::std::vector<Attribute>()) : - outer_attrs(::std::move(outer_attrs)) {}*/ - - // Clone function implementation as pure virtual method - virtual TraitItem* clone_trait_item_impl() const = 0; - - public: - virtual ~TraitItem() {} - - // Returns whether TraitItem has outer attributes. - /*inline bool has_outer_attrs() const { - return !outer_attrs.empty(); - }*/ - - // Unique pointer custom clone function - ::std::unique_ptr<TraitItem> clone_trait_item() const { - return ::std::unique_ptr<TraitItem>(clone_trait_item_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - }; - - // Abstract base class for items used within an inherent impl block (the impl name {} one) - class InherentImplItem { - protected: - // Clone function implementation as pure virtual method - virtual InherentImplItem* clone_inherent_impl_item_impl() const = 0; - - public: - virtual ~InherentImplItem() {} - - // Unique pointer custom clone function - ::std::unique_ptr<InherentImplItem> clone_inherent_impl_item() const { - return ::std::unique_ptr<InherentImplItem>(clone_inherent_impl_item_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - }; - - // Abstract base class for items used in a trait impl - class TraitImplItem { - protected: - virtual TraitImplItem* clone_trait_impl_item_impl() const = 0; - - public: - virtual ~TraitImplItem(){}; - - // Unique pointer custom clone function - ::std::unique_ptr<TraitImplItem> clone_trait_impl_item() const { - return ::std::unique_ptr<TraitImplItem>(clone_trait_impl_item_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - }; - - // A macro invocation item (or statement) AST node (i.e. semi-coloned macro invocation) - class MacroInvocationSemi - : public MacroItem - , public TraitItem - , public InherentImplItem - , public TraitImplItem - /*, public Statement*/ { - // already inherits from statement indirectly via item as item is a subclass of statement - SimplePath path; - // all delim types except curly must have invocation end with a semicolon - DelimType delim_type; - //::std::vector<TokenTree> token_trees; - ::std::vector< ::std::unique_ptr<TokenTree> > token_trees; - - Location locus; - - public: - ::std::string as_string() const; - - MacroInvocationSemi(SimplePath macro_path, DelimType delim_type, - ::std::vector< ::std::unique_ptr<TokenTree> > token_trees, - ::std::vector<Attribute> outer_attribs, Location locus) : - MacroItem(::std::move(outer_attribs)), - path(::std::move(macro_path)), delim_type(delim_type), - token_trees(::std::move(token_trees)), locus(locus) {} - /* TODO: possible issue with Item and TraitItem hierarchies both having outer attributes - * - storage inefficiency at least. - * Best current idea is to make Item preferred and have TraitItem get virtual functions - * for attributes or something. - * Or just redo the "composition" approach, but then this prevents polymorphism and would - * entail redoing quite a bit of the parser. */ - - // Copy constructor with vector clone - MacroInvocationSemi(MacroInvocationSemi const& other) : - MacroItem(other), TraitItem(other), InherentImplItem(other), TraitImplItem(other), - path(other.path), delim_type(other.delim_type), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - token_trees.reserve(other.token_trees.size()); - - for (const auto& e : other.token_trees) { - token_trees.push_back(e->clone_token_tree()); - } - } - - // Overloaded assignment operator to vector clone - MacroInvocationSemi& operator=(MacroInvocationSemi const& other) { - MacroItem::operator=(other); - TraitItem::operator=(other); - InherentImplItem::operator=(other); - TraitImplItem::operator=(other); - path = other.path; - delim_type = other.delim_type; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - token_trees.reserve(other.token_trees.size()); - - for (const auto& e : other.token_trees) { - token_trees.push_back(e->clone_token_tree()); - } - - return *this; - } - - // Move constructors - MacroInvocationSemi(MacroInvocationSemi&& other) = default; - MacroInvocationSemi& operator=(MacroInvocationSemi&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocationSemi* clone_item_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocationSemi* clone_inherent_impl_item_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocationSemi* clone_trait_impl_item_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - } - - // FIXME: remove if item impl virtual override works properly - // Use covariance to implement clone function as returning this object rather than base - /*virtual MacroInvocationSemi* clone_statement_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - }*/ - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocationSemi* clone_trait_item_impl() const OVERRIDE { - return new MacroInvocationSemi(*this); - } - }; - - // A crate AST object - holds all the data for a single compilation unit - struct Crate { - bool has_utf8bom; - bool has_shebang; - - ::std::vector<Attribute> inner_attrs; - //::std::vector<Item> items; - // dodgy spacing required here - // TODO: is it better to have a vector of items here or a module (implicit top-level one)? - ::std::vector< ::std::unique_ptr<Item> > items; - - public: - // Constructor - Crate(::std::vector< ::std::unique_ptr<Item> > items, - ::std::vector<Attribute> inner_attrs, bool has_utf8bom = false, - bool has_shebang = false) : - has_utf8bom(has_utf8bom), - has_shebang(has_shebang), inner_attrs(::std::move(inner_attrs)), - items(::std::move(items)) {} - - // Copy constructor with vector clone - Crate(Crate const& other) : - has_utf8bom(other.has_utf8bom), has_shebang(other.has_shebang), - inner_attrs(other.inner_attrs) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_item()); - } - } - - ~Crate() = default; - - // Overloaded assignment operator with vector clone - Crate& operator=(Crate const& other) { - inner_attrs = other.inner_attrs; - has_shebang = other.has_shebang; - has_utf8bom = other.has_utf8bom; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_item()); - } - - return *this; - } - - // Move constructors - Crate(Crate&& other) = default; - Crate& operator=(Crate&& other) = default; - - // Get crate representation as string (e.g. for debugging). - ::std::string as_string() const; - }; - - // Base path expression AST node - abstract - class PathExpr : public ExprWithoutBlock { - protected: - PathExpr(::std::vector<Attribute> outer_attribs) : - ExprWithoutBlock(::std::move(outer_attribs)) {} - - public: - // TODO: think of a better and less hacky way to allow this - - // Replaces the outer attributes of this path expression with the given outer attributes. - void replace_outer_attrs(::std::vector<Attribute> outer_attrs) { - set_outer_attrs(::std::move(outer_attrs)); - } - }; + // Sets node's Location. + void set_locus(Location loc_) { + loc = loc_; } -} + + // Get node output as a string. Pure virtual. + virtual ::std::string as_string() const = 0; + + virtual ~Node() {} + + // TODO: constructor including Location? Make all derived classes have +Location? + + private: + // The node's location. + Location loc; +};*/ +// decided to not have node as a "node" would never need to be stored + +// Attribute body - abstract base class +class AttrInput +{ +public: + virtual ~AttrInput () {} + + // Unique pointer custom clone function + ::std::unique_ptr<AttrInput> clone_attr_input () const + { + return ::std::unique_ptr<AttrInput> (clone_attr_input_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + virtual bool check_cfg_predicate (const Session &session) const = 0; + + // Parse attribute input to meta item, if possible + virtual AttrInput *parse_to_meta_item () const { return NULL; } + +protected: + // pure virtual clone implementation + virtual AttrInput *clone_attr_input_impl () const = 0; +}; + +// forward decl for use in token tree method +class Token; + +// A tree of tokens (or a single token) - abstract base class +class TokenTree +{ +public: + virtual ~TokenTree () {} + + // Unique pointer custom clone function + ::std::unique_ptr<TokenTree> clone_token_tree () const + { + return ::std::unique_ptr<TokenTree> (clone_token_tree_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + /* Converts token tree to a flat token stream. Tokens must be pointer to avoid + * mutual dependency with Token. */ + virtual ::std::vector< ::std::unique_ptr<Token> > + to_token_stream () const = 0; + +protected: + // pure virtual clone implementation + virtual TokenTree *clone_token_tree_impl () const = 0; +}; + +// Abstract base class for a macro match +class MacroMatch +{ +public: + virtual ~MacroMatch () {} + + virtual ::std::string as_string () const = 0; + + // Unique pointer custom clone function + ::std::unique_ptr<MacroMatch> clone_macro_match () const + { + return ::std::unique_ptr<MacroMatch> (clone_macro_match_impl ()); + } + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // pure virtual clone implementation + virtual MacroMatch *clone_macro_match_impl () const = 0; +}; + +// A token is a kind of token tree (except delimiter tokens) +class Token : public TokenTree, public MacroMatch +{ + // A token is a kind of token tree (except delimiter tokens) + // A token is a kind of MacroMatch (except $ and delimiter tokens) + // TODO: improve member variables - current ones are the same as lexer token + // Token kind. + TokenId token_id; + // Token location. + Location locus; + // Associated text (if any) of token. + std::string str; + // Token type hint (if any). + PrimitiveCoreType type_hint; + +public: + // Unique pointer custom clone function + ::std::unique_ptr<Token> clone_token () const + { + return ::std::unique_ptr<Token> (clone_token_impl ()); + } + + // constructor from general text - avoid using if lexer const_TokenPtr is + // available + Token (TokenId token_id, Location locus, ::std::string str, + PrimitiveCoreType type_hint) + : token_id (token_id), locus (locus), str (::std::move (str)), + type_hint (type_hint) + {} + + // Constructor from lexer const_TokenPtr + /* TODO: find workaround for std::string being NULL - probably have to + * introduce new method in lexer Token, or maybe make conversion method + * there*/ + Token (const_TokenPtr lexer_token_ptr) + : token_id (lexer_token_ptr->get_id ()), + locus (lexer_token_ptr->get_locus ()), str (""), + type_hint (lexer_token_ptr->get_type_hint ()) + { + // FIXME: change to "should have str" later? + if (lexer_token_ptr->has_str ()) + { + str = lexer_token_ptr->get_str (); + + // DEBUG + fprintf (stderr, "ast token created with str '%s'\n", str.c_str ()); + } + else + { + // FIXME: is this returning correct thing? + str = lexer_token_ptr->get_token_description (); + + // DEBUG + fprintf (stderr, "ast token created with string '%s'\n", str.c_str ()); + } + + // DEBUG + if (lexer_token_ptr->should_have_str () && !lexer_token_ptr->has_str ()) + { + fprintf (stderr, + "BAD: for token '%s', should have string but does not!\n", + lexer_token_ptr->get_token_description ()); + } + } + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + // Return copy of itself but in token stream form. + virtual ::std::vector< ::std::unique_ptr<Token> > + to_token_stream () const OVERRIDE; + + TokenId get_id () const { return token_id; } + + Location get_locus () const { return locus; } + +protected: + // No virtual for now as not polymorphic but can be in future + /*virtual*/ Token *clone_token_impl () const { return new Token (*this); } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual Token *clone_token_tree_impl () const OVERRIDE + { + return new Token (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual Token *clone_macro_match_impl () const OVERRIDE + { + return new Token (*this); + } +}; + +// A literal - value with a type. Used in LiteralExpr and LiteralPattern. +struct Literal +{ +public: + enum LitType + { + CHAR, + STRING, + RAW_STRING, + BYTE, + BYTE_STRING, + RAW_BYTE_STRING, + INT, + FLOAT, + BOOL + }; + +private: + // TODO: maybe make subclasses of each type of literal with their typed values + // (or generics) + ::std::string value_as_string; + LitType type; + +public: + ::std::string as_string () const { return value_as_string; } + + inline LitType get_lit_type () const { return type; } + + Literal (::std::string value_as_string, LitType type) + : value_as_string (::std::move (value_as_string)), type (type) + {} + + static Literal create_error () { return Literal ("", CHAR); } + + // Returns whether literal is in an invalid state. + bool is_error () const { return value_as_string == ""; } +}; + +// A token tree with delimiters +class DelimTokenTree : public TokenTree, public AttrInput +{ + DelimType delim_type; + ::std::vector< ::std::unique_ptr<TokenTree> > token_trees; + + Location locus; + + // TODO: move all the "parse" functions into a separate class that has the + // token stream reference - will be cleaner Parse a meta item inner. + //::std::unique_ptr<MetaItemInner> parse_meta_item_inner(const ::std::vector< + //::std::unique_ptr<Token> >& token_stream, int& i) const; SimplePath + // parse_simple_path(const ::std::vector< ::std::unique_ptr<Token> >& + // token_stream, int& i) const; SimplePathSegment + // parse_simple_path_segment(const ::std::vector< + // ::std::unique_ptr<Token> >& token_stream, int& i) const; + //::std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit(const + //::std::unique_ptr<Token>& + // tok) const; + //::std::vector< ::std::unique_ptr<MetaItemInner> > parse_meta_item_seq(const + //::std::vector< ::std::unique_ptr<Token> >& token_stream, int& i) const; + //Literal + // parse_literal(const ::std::unique_ptr<Token>& tok) const; + //::std::unique_ptr<MetaItem> parse_path_meta_item(const ::std::vector< + //::std::unique_ptr<Token> >& token_stream, int& i) const; bool + // is_end_meta_item_tok(TokenId tok) const; + +protected: + // Use covariance to implement clone function as returning a DelimTokenTree + // object + virtual DelimTokenTree *clone_attr_input_impl () const OVERRIDE + { + return new DelimTokenTree (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual DelimTokenTree *clone_token_tree_impl () const OVERRIDE + { + return new DelimTokenTree (*this); + } + +public: + DelimTokenTree (DelimType delim_type, + ::std::vector< ::std::unique_ptr<TokenTree> > token_trees + = ::std::vector< ::std::unique_ptr<TokenTree> > (), + Location locus = Location ()) + : delim_type (delim_type), token_trees (::std::move (token_trees)), + locus (locus) + {} + + // Copy constructor with vector clone + DelimTokenTree (DelimTokenTree const &other) + : delim_type (other.delim_type), locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + token_trees.reserve (other.token_trees.size ()); + + for (const auto &e : other.token_trees) + { + token_trees.push_back (e->clone_token_tree ()); + } + } + + // overloaded assignment operator with vector clone + DelimTokenTree &operator= (DelimTokenTree const &other) + { + delim_type = other.delim_type; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + token_trees.reserve (other.token_trees.size ()); + + for (const auto &e : other.token_trees) + { + token_trees.push_back (e->clone_token_tree ()); + } + + return *this; + } + + // move constructors + DelimTokenTree (DelimTokenTree &&other) = default; + DelimTokenTree &operator= (DelimTokenTree &&other) = default; + + static DelimTokenTree create_empty () { return DelimTokenTree (PARENS); } + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + virtual bool + check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const OVERRIDE + { + // this should never be called - should be converted first + return false; + } + + virtual AttrInput *parse_to_meta_item () const OVERRIDE; + + virtual ::std::vector< ::std::unique_ptr<Token> > + to_token_stream () const OVERRIDE; +}; + +// Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to +// be defined +class AttrInputLiteral; + +// TODO: move applicable stuff into here or just don't include it because +// nothing uses it A segment of a path (maybe) +class PathSegment +{ +public: + virtual ~PathSegment () {} + + virtual ::std::string as_string () const = 0; + + // TODO: add visitor here? +}; + +// A segment of a simple path without generic or type arguments +class SimplePathSegment : public PathSegment +{ + ::std::string segment_name; + Location locus; + + // only allow identifiers, "super", "self", "crate", or "$crate" +public: + // TODO: put checks in constructor to enforce this rule? + SimplePathSegment (::std::string segment_name, Location locus = Location ()) + : segment_name (::std::move (segment_name)), locus (locus) + {} + + // Returns whether simple path segment is in an invalid state (currently, if + // empty). + inline bool is_error () const { return segment_name.empty (); } + + // Creates an error SimplePathSegment + static SimplePathSegment create_error () + { + return SimplePathSegment (::std::string ("")); + } + + ::std::string as_string () const; + + inline Location get_locus () const { return locus; } + + // TODO: visitor pattern? +}; + +// A simple path without generic or type arguments +class SimplePath +{ + bool has_opening_scope_resolution; + ::std::vector<SimplePathSegment> segments; + Location locus; + +public: + // Constructor + SimplePath (::std::vector<SimplePathSegment> path_segments, + bool has_opening_scope_resolution = false, + Location locus = Location ()) + : has_opening_scope_resolution (has_opening_scope_resolution), + segments (::std::move (path_segments)), locus (locus) + {} + + // Creates an empty SimplePath. + static SimplePath create_empty () + { + return SimplePath (::std::vector<SimplePathSegment> ()); + } + + // Returns whether the SimplePath is empty, i.e. has path segments. + inline bool is_empty () const { return segments.empty (); } + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + // does this need visitor if not polymorphic? probably not + + // path-to-string comparison operator + bool operator== (const ::std::string &rhs) + { + return !has_opening_scope_resolution && segments.size () == 1 + && segments[0].as_string () == rhs; + } + + /* Creates a single-segment SimplePath from a string. This will not check to + * ensure that this is a valid identifier in path, so be careful. Also, this + * will have no location data. + * TODO have checks? */ + static SimplePath from_str (::std::string str) + { + ::std::vector<AST::SimplePathSegment> single_segments + = {AST::SimplePathSegment (::std::move (str))}; + return SimplePath (::std::move (single_segments)); + } +}; + +// aka Attr +// Attribute AST representation +struct Attribute +{ +private: + SimplePath path; + + // bool has_attr_input; + // AttrInput* attr_input; + ::std::unique_ptr<AttrInput> attr_input; + + Location locus; + + // TODO: maybe a variable storing whether attr input is parsed or not + +public: + // Returns whether Attribute has AttrInput + inline bool has_attr_input () const { return attr_input != NULL; } + + // Constructor has pointer AttrInput for polymorphism reasons + Attribute (SimplePath path, ::std::unique_ptr<AttrInput> input, + Location locus = Location ()) + : path (::std::move (path)), attr_input (::std::move (input)), locus (locus) + {} + + // Copy constructor must deep copy attr_input as unique pointer + Attribute (Attribute const &other) : path (other.path), locus (other.locus) + { + // guard to protect from null pointer dereference + if (other.attr_input != NULL) + { + attr_input = other.attr_input->clone_attr_input (); + } + } + + // default destructor + ~Attribute () = default; + + // overload assignment operator to use custom clone method + Attribute &operator= (Attribute const &other) + { + path = other.path; + locus = other.locus; + // guard to protect from null pointer dereference + if (other.attr_input != NULL) + { + attr_input = other.attr_input->clone_attr_input (); + } + + return *this; + } + + // default move semantics + Attribute (Attribute &&other) = default; + Attribute &operator= (Attribute &&other) = default; + + // Unique pointer custom clone function + ::std::unique_ptr<Attribute> clone_attribute () const + { + return ::std::unique_ptr<Attribute> (clone_attribute_impl ()); + } + + /*~Attribute() { + delete attr_input; + }*/ + + // Creates an empty attribute (which is invalid) + static Attribute create_empty () + { + return Attribute (SimplePath::create_empty (), NULL); + } + + // Returns whether the attribute is considered an "empty" attribute. + inline bool is_empty () const + { + return attr_input == NULL && path.is_empty (); + } + + /* e.g.: + #![crate_type = "lib"] + #[test] + #[cfg(target_os = "linux")] + #[allow(non_camel_case_types)] + #![allow(unused_variables)] + */ + + // Full built-in attribute list: + /* cfg + * cfg_attr + * test + * ignore + * should_panic + * derive + * macro_export + * macro_use + * proc_macro + * proc_macro_derive + * proc_macro_attribute + * allow + * warn + * deny + * forbid + * deprecated + * must_use + * link + * link_name + * no_link + * repr + * crate_type + * no_main + * export_name + * link_section + * no_mangle + * used + * crate_name + * inline + * cold + * no_builtins + * target_feature + * doc + * no_std + * no_implicit_prelude + * path + * recursion_limit + * type_length_limit + * panic_handler + * global_allocator + * windows_subsystem + * feature */ + + ::std::string as_string () const; + + // TODO: does this require visitor pattern as not polymorphic? + + // Maybe change to const-reference in future + SimplePath get_path () const { return path; } + + // Call to parse attribute body to meta item syntax. + void parse_attr_to_meta_item (); + + // Determines whether cfg predicate is true and item with attribute should not + // be stripped. + bool check_cfg_predicate (const Session &session) + { + // assume that cfg predicate actually can exist, i.e. attribute has cfg or + // cfg_attr path + + if (!has_attr_input ()) + { + return false; + } + + // TODO: maybe replace with storing a "has been parsed" variable? + parse_attr_to_meta_item (); + // can't be const because of this anyway + + return attr_input->check_cfg_predicate (session); + } + +protected: + // not virtual as currently no subclasses of Attribute, but could be in future + /*virtual*/ Attribute *clone_attribute_impl () const + { + return new Attribute (*this); + } +}; + +// Forward decl - defined in rust-macro.h +class MetaNameValueStr; + +// abstract base meta item inner class +class MetaItemInner +{ +protected: + // pure virtual as MetaItemInner + virtual MetaItemInner *clone_meta_item_inner_impl () const = 0; + +public: + // Unique pointer custom clone function + ::std::unique_ptr<MetaItemInner> clone_meta_item_inner () const + { + return ::std::unique_ptr<MetaItemInner> (clone_meta_item_inner_impl ()); + } + + virtual ~MetaItemInner () {} + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + + // HACK: used to simplify parsing - creates a copy of that type, or returns + // null + virtual MetaNameValueStr *to_meta_name_value_str () const { return NULL; } + + // HACK: used to simplify parsing - same thing + virtual SimplePath to_path_item () const + { + return SimplePath::create_empty (); + } + + virtual bool check_cfg_predicate (const Session &session) const = 0; +}; + +// Container used to store MetaItems as AttrInput (bridge-ish kinda thing) +class AttrInputMetaItemContainer : public AttrInput +{ + ::std::vector< ::std::unique_ptr<MetaItemInner> > items; + +public: + AttrInputMetaItemContainer ( + ::std::vector< ::std::unique_ptr<MetaItemInner> > items) + : items (::std::move (items)) + {} + + // copy constructor with vector clone + AttrInputMetaItemContainer (const AttrInputMetaItemContainer &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + items.reserve (other.items.size ()); + + for (const auto &e : other.items) + { + items.push_back (e->clone_meta_item_inner ()); + } + } + + // no destructor definition required + + // copy assignment operator with vector clone + AttrInputMetaItemContainer & + operator= (const AttrInputMetaItemContainer &other) + { + AttrInput::operator= (other); + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + items.reserve (other.items.size ()); + + for (const auto &e : other.items) + { + items.push_back (e->clone_meta_item_inner ()); + } + + return *this; + } + + // default move constructors + AttrInputMetaItemContainer (AttrInputMetaItemContainer &&other) = default; + AttrInputMetaItemContainer &operator= (AttrInputMetaItemContainer &&other) + = default; + + ::std::string as_string () const OVERRIDE; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + virtual bool check_cfg_predicate (const Session &session) const OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this type + virtual AttrInputMetaItemContainer *clone_attr_input_impl () const OVERRIDE + { + return new AttrInputMetaItemContainer (*this); + } +}; + +// abstract base meta item class +class MetaItem : public MetaItemInner +{ +}; + +// Forward decl - defined in rust-expr.h +class MetaItemLitExpr; + +// Forward decl - defined in rust-expr.h +class MetaItemPathLit; + +// Forward decl - defined in rust-macro.h +class MetaItemPath; + +// Forward decl - defined in rust-macro.h +class MetaItemSeq; + +// Forward decl - defined in rust-macro.h +class MetaWord; + +// Forward decl - defined in rust-macro.h +class MetaListPaths; + +// Forward decl - defined in rust-macro.h +struct 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: + // Unique pointer custom clone function + ::std::unique_ptr<Stmt> clone_stmt () const + { + return ::std::unique_ptr<Stmt> (clone_stmt_impl ()); + } + + virtual ~Stmt () {} + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // Clone function implementation as pure virtual method + virtual Stmt *clone_stmt_impl () const = 0; +}; + +// Rust "item" AST node (declaration of top-level/module-level allowed stuff) +class Item : public Stmt +{ + ::std::vector<Attribute> outer_attrs; + + // TODO: should outer attrs be defined here or in each derived class? + +public: + // Unique pointer custom clone function + ::std::unique_ptr<Item> clone_item () const + { + return ::std::unique_ptr<Item> (clone_item_impl ()); + } + + ::std::string as_string () const; + + // Adds crate names to the vector passed by reference, if it can + // (polymorphism). + virtual void + add_crate_name (::std::vector< ::std::string> &names ATTRIBUTE_UNUSED) const + {} + +protected: + // Constructor + Item (::std::vector<Attribute> outer_attribs = ::std::vector<Attribute> ()) + : outer_attrs (::std::move (outer_attribs)) + {} + + // Clone function implementation as pure virtual method + virtual Item *clone_item_impl () const = 0; + + /* Save having to specify two clone methods in derived classes by making + * statement clone return item clone. Hopefully won't affect performance too + * much. */ + virtual Item *clone_stmt_impl () const OVERRIDE { return clone_item_impl (); } +}; + +// forward decl of ExprWithoutBlock +class ExprWithoutBlock; + +// Base expression AST node - abstract +class Expr +{ + // TODO: move outer attribute data to derived classes? + ::std::vector<Attribute> outer_attrs; + +public: + inline const ::std::vector<Attribute> &get_outer_attrs () const + { + return outer_attrs; + } + + // Unique pointer custom clone function + ::std::unique_ptr<Expr> clone_expr () const + { + return ::std::unique_ptr<Expr> (clone_expr_impl ()); + } + + /* TODO: public methods that could be useful: + * - get_type() - returns type of expression. set_type() may also be useful + * for some? + * - evaluate() - evaluates expression if constant? can_evaluate()? */ + + // HACK: downcasting without dynamic_cast (if possible) via polymorphism - + // overrided in subclasses of ExprWithoutBlock + virtual ExprWithoutBlock *as_expr_without_block () const + { + // DEBUG + fprintf ( + stderr, + "clone expr without block returns null and has not been overriden\n"); + + return NULL; + } + + // TODO: make pure virtual if move out outer attributes to derived classes + virtual ::std::string as_string () const; + + virtual ~Expr () {} + + // HACK: slow way of getting location from base expression through virtual + // methods. + virtual Location get_locus_slow () const { return Location (); } + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // Constructor + Expr (::std::vector<Attribute> outer_attribs = ::std::vector<Attribute> ()) + : outer_attrs (::std::move (outer_attribs)) + {} + + // Clone function implementation as pure virtual method + virtual Expr *clone_expr_impl () const = 0; + + // TODO: think of less hacky way to implement this kind of thing + // Sets outer attributes. + void set_outer_attrs (::std::vector<Attribute> outer_attrs_to_set) + { + outer_attrs = ::std::move (outer_attrs_to_set); + } +}; + +// AST node for an expression without an accompanying block - abstract +class ExprWithoutBlock : public Expr +{ +protected: + // Constructor + ExprWithoutBlock (::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : Expr (::std::move (outer_attribs)) + {} + + // pure virtual clone implementation + virtual ExprWithoutBlock *clone_expr_without_block_impl () const = 0; + + /* Save having to specify two clone methods in derived classes by making expr + * clone + * return exprwithoutblock clone. Hopefully won't affect performance too much. + */ + virtual ExprWithoutBlock *clone_expr_impl () const OVERRIDE + { + return clone_expr_without_block_impl (); + } + +public: + // Unique pointer custom clone function + ::std::unique_ptr<ExprWithoutBlock> clone_expr_without_block () const + { + return ::std::unique_ptr<ExprWithoutBlock> ( + clone_expr_without_block_impl ()); + } + + // downcasting hack from expr to use pratt parsing with + // parse_expr_without_block + virtual ExprWithoutBlock *as_expr_without_block () const OVERRIDE + { + // DEBUG + fprintf (stderr, "about to call the impl for clone expr without block\n"); + + return clone_expr_without_block_impl (); + } +}; + +// HACK: IdentifierExpr, delete when figure out identifier vs expr problem in +// Pratt parser Alternatively, identifiers could just be represented as +// single-segment paths +class IdentifierExpr : public ExprWithoutBlock +{ + Identifier ident; + + Location locus; + +public: + IdentifierExpr (Identifier ident, Location locus = Location (), + ::std::vector<Attribute> outer_attrs + = ::std::vector<Attribute> ()) + : ExprWithoutBlock (::std::move (outer_attrs)), ident (::std::move (ident)), + locus (locus) + {} + + ::std::string as_string () const OVERRIDE { return ident; } + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Clone method implementation + virtual IdentifierExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new IdentifierExpr (*this); + } +}; + +// Pattern base AST node +class Pattern +{ +public: + // Unique pointer custom clone function + ::std::unique_ptr<Pattern> clone_pattern () const + { + return ::std::unique_ptr<Pattern> (clone_pattern_impl ()); + } + + // possible virtual methods: is_refutable() + + virtual ~Pattern () {} + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // Clone pattern implementation as pure virtual method + virtual Pattern *clone_pattern_impl () const = 0; +}; + +// forward decl for Type +class TraitBound; + +// Base class for types as represented in AST - abstract +class Type +{ +public: + // Unique pointer custom clone function + ::std::unique_ptr<Type> clone_type () const + { + return ::std::unique_ptr<Type> (clone_type_impl ()); + } + + // virtual destructor + virtual ~Type () {} + + virtual ::std::string as_string () const = 0; + + // HACK: convert to trait bound. Virtual method overriden by classes that + // enable this. + virtual TraitBound *to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const + { + return NULL; + } + // as pointer, shouldn't require definition beforehand, only forward + // declaration. + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // Clone function implementation as pure virtual method + virtual Type *clone_type_impl () const = 0; +}; + +// A type without parentheses? - abstract +class TypeNoBounds : public Type +{ +public: + // Unique pointer custom clone function + ::std::unique_ptr<TypeNoBounds> clone_type_no_bounds () const + { + return ::std::unique_ptr<TypeNoBounds> (clone_type_no_bounds_impl ()); + } + +protected: + // Clone function implementation as pure virtual method + virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0; + + /* Save having to specify two clone methods in derived classes by making type + * clone return typenobounds clone. Hopefully won't affect performance too + * much. */ + virtual TypeNoBounds *clone_type_impl () const OVERRIDE + { + return clone_type_no_bounds_impl (); + } +}; + +// Abstract base class representing a type param bound - Lifetime and TraitBound +// extends it +class TypeParamBound +{ +public: + virtual ~TypeParamBound () {} + + // Unique pointer custom clone function + ::std::unique_ptr<TypeParamBound> clone_type_param_bound () const + { + return ::std::unique_ptr<TypeParamBound> (clone_type_param_bound_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // Clone function implementation as pure virtual method + virtual TypeParamBound *clone_type_param_bound_impl () const = 0; +}; + +// Represents a lifetime (and is also a kind of type param bound) +class Lifetime : public TypeParamBound +{ +public: + enum LifetimeType + { + NAMED, // corresponds to LIFETIME_OR_LABEL + STATIC, // corresponds to 'static + WILDCARD // corresponds to '_ + }; + +private: + LifetimeType lifetime_type; + + // TODO: LIFETIME_OR_LABEL (aka lifetime token) is only field + // find way of enclosing token or something + ::std::string lifetime_name; + // only applies for NAMED lifetime_type + + Location locus; + +public: + // Constructor + Lifetime (LifetimeType type, ::std::string name = ::std::string (), + Location locus = Location ()) + : lifetime_type (type), lifetime_name (::std::move (name)), locus (locus) + {} + + // Creates an "error" lifetime. + static Lifetime error () { return Lifetime (NAMED, ::std::string ("")); } + + // Returns true if the lifetime is in an error state. + inline bool is_error () const + { + return lifetime_type == NAMED && lifetime_name.empty (); + } + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual Lifetime *clone_type_param_bound_impl () const OVERRIDE + { + return new Lifetime (*this); + } +}; + +// Base generic parameter in AST. Abstract - can be represented by a Lifetime or +// Type param +class GenericParam +{ +public: + virtual ~GenericParam () {} + + // Unique pointer custom clone function + ::std::unique_ptr<GenericParam> clone_generic_param () const + { + return ::std::unique_ptr<GenericParam> (clone_generic_param_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // Clone function implementation as pure virtual method + virtual GenericParam *clone_generic_param_impl () const = 0; +}; + +// A lifetime generic parameter (as opposed to a type generic parameter) +class LifetimeParam : public GenericParam +{ + Lifetime lifetime; + + // bool has_lifetime_bounds; + // LifetimeBounds lifetime_bounds; + ::std::vector<Lifetime> lifetime_bounds; // inlined LifetimeBounds + + // bool has_outer_attribute; + //::std::unique_ptr<Attribute> outer_attr; + Attribute outer_attr; + + Location locus; + +public: + // Returns whether the lifetime param has any lifetime bounds. + inline bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); } + + // Returns whether the lifetime param has an outer attribute. + inline bool has_outer_attribute () const { return !outer_attr.is_empty (); } + + // Creates an error state lifetime param. + static LifetimeParam create_error () + { + return LifetimeParam (Lifetime::error ()); + } + + // Returns whether the lifetime param is in an error state. + inline bool is_error () const { return lifetime.is_error (); } + + // Constructor + LifetimeParam (Lifetime lifetime, Location locus = Location (), + ::std::vector<Lifetime> lifetime_bounds + = ::std::vector<Lifetime> (), + Attribute outer_attr = Attribute::create_empty ()) + : lifetime (::std::move (lifetime)), + lifetime_bounds (::std::move (lifetime_bounds)), + outer_attr (::std::move (outer_attr)), locus (locus) + {} + + // TODO: remove copy and assignment operator definitions - not required + + // Copy constructor with clone + LifetimeParam (LifetimeParam const &other) + : lifetime (other.lifetime), lifetime_bounds (other.lifetime_bounds), + outer_attr (other.outer_attr), locus (other.locus) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone attribute + LifetimeParam &operator= (LifetimeParam const &other) + { + lifetime = other.lifetime; + lifetime_bounds = other.lifetime_bounds; + outer_attr = other.outer_attr; + locus = other.locus; + + return *this; + } + + // move constructors + LifetimeParam (LifetimeParam &&other) = default; + LifetimeParam &operator= (LifetimeParam &&other) = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual LifetimeParam *clone_generic_param_impl () const OVERRIDE + { + return new LifetimeParam (*this); + } +}; + +// A macro item AST node - potentially abstract base class +class MacroItem : public Item +{ + /*public: + ::std::string as_string() const;*/ +protected: + MacroItem (::std::vector<Attribute> outer_attribs) + : Item (::std::move (outer_attribs)) + {} +}; + +// Item used in trait declarations - abstract base class +class TraitItem +{ + // bool has_outer_attrs; + // TODO: remove and rely on virtual functions and VisItem-derived attributes? + //::std::vector<Attribute> outer_attrs; + + // NOTE: all children should have outer attributes + +protected: + // Constructor + /*TraitItem(::std::vector<Attribute> outer_attrs = ::std::vector<Attribute>()) + : outer_attrs(::std::move(outer_attrs)) {}*/ + + // Clone function implementation as pure virtual method + virtual TraitItem *clone_trait_item_impl () const = 0; + +public: + virtual ~TraitItem () {} + + // Returns whether TraitItem has outer attributes. + /*inline bool has_outer_attrs() const { + return !outer_attrs.empty(); + }*/ + + // Unique pointer custom clone function + ::std::unique_ptr<TraitItem> clone_trait_item () const + { + return ::std::unique_ptr<TraitItem> (clone_trait_item_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; +}; + +// Abstract base class for items used within an inherent impl block (the impl +// name {} one) +class InherentImplItem +{ +protected: + // Clone function implementation as pure virtual method + virtual InherentImplItem *clone_inherent_impl_item_impl () const = 0; + +public: + virtual ~InherentImplItem () {} + + // Unique pointer custom clone function + ::std::unique_ptr<InherentImplItem> clone_inherent_impl_item () const + { + return ::std::unique_ptr<InherentImplItem> ( + clone_inherent_impl_item_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; +}; + +// Abstract base class for items used in a trait impl +class TraitImplItem +{ +protected: + virtual TraitImplItem *clone_trait_impl_item_impl () const = 0; + +public: + virtual ~TraitImplItem (){}; + + // Unique pointer custom clone function + ::std::unique_ptr<TraitImplItem> clone_trait_impl_item () const + { + return ::std::unique_ptr<TraitImplItem> (clone_trait_impl_item_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; +}; + +// A macro invocation item (or statement) AST node (i.e. semi-coloned macro +// invocation) +class MacroInvocationSemi : public MacroItem, + public TraitItem, + public InherentImplItem, + public TraitImplItem +/*, public Statement*/ { + // already inherits from statement indirectly via item as item is a subclass + // of statement + SimplePath path; + // all delim types except curly must have invocation end with a semicolon + DelimType delim_type; + //::std::vector<TokenTree> token_trees; + ::std::vector< ::std::unique_ptr<TokenTree> > token_trees; + + Location locus; + +public: + ::std::string as_string () const; + + MacroInvocationSemi ( + SimplePath macro_path, DelimType delim_type, + ::std::vector< ::std::unique_ptr<TokenTree> > token_trees, + ::std::vector<Attribute> outer_attribs, Location locus) + : MacroItem (::std::move (outer_attribs)), path (::std::move (macro_path)), + delim_type (delim_type), token_trees (::std::move (token_trees)), + locus (locus) + {} + /* TODO: possible issue with Item and TraitItem hierarchies both having outer + * attributes + * - storage inefficiency at least. + * Best current idea is to make Item preferred and have TraitItem get virtual + * functions for attributes or something. Or just redo the "composition" + * approach, but then this prevents polymorphism and would entail redoing + * quite a bit of the parser. */ + + // Copy constructor with vector clone + MacroInvocationSemi (MacroInvocationSemi const &other) + : MacroItem (other), TraitItem (other), InherentImplItem (other), + TraitImplItem (other), path (other.path), delim_type (other.delim_type), + locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + token_trees.reserve (other.token_trees.size ()); + + for (const auto &e : other.token_trees) + { + token_trees.push_back (e->clone_token_tree ()); + } + } + + // Overloaded assignment operator to vector clone + MacroInvocationSemi &operator= (MacroInvocationSemi const &other) + { + MacroItem::operator= (other); + TraitItem::operator= (other); + InherentImplItem::operator= (other); + TraitImplItem::operator= (other); + path = other.path; + delim_type = other.delim_type; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + token_trees.reserve (other.token_trees.size ()); + + for (const auto &e : other.token_trees) + { + token_trees.push_back (e->clone_token_tree ()); + } + + return *this; + } + + // Move constructors + MacroInvocationSemi (MacroInvocationSemi &&other) = default; + MacroInvocationSemi &operator= (MacroInvocationSemi &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroInvocationSemi *clone_item_impl () const OVERRIDE + { + return new MacroInvocationSemi (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroInvocationSemi *clone_inherent_impl_item_impl () const OVERRIDE + { + return new MacroInvocationSemi (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroInvocationSemi *clone_trait_impl_item_impl () const OVERRIDE + { + return new MacroInvocationSemi (*this); + } + + // FIXME: remove if item impl virtual override works properly + // Use covariance to implement clone function as returning this object rather + // than base + /*virtual MacroInvocationSemi* clone_statement_impl() const OVERRIDE { + return new MacroInvocationSemi(*this); + }*/ + + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroInvocationSemi *clone_trait_item_impl () const OVERRIDE + { + return new MacroInvocationSemi (*this); + } +}; + +// A crate AST object - holds all the data for a single compilation unit +struct Crate +{ + bool has_utf8bom; + bool has_shebang; + + ::std::vector<Attribute> inner_attrs; + //::std::vector<Item> items; + // dodgy spacing required here + // TODO: is it better to have a vector of items here or a module (implicit + // top-level one)? + ::std::vector< ::std::unique_ptr<Item> > items; + +public: + // Constructor + Crate (::std::vector< ::std::unique_ptr<Item> > items, + ::std::vector<Attribute> inner_attrs, bool has_utf8bom = false, + bool has_shebang = false) + : has_utf8bom (has_utf8bom), has_shebang (has_shebang), + inner_attrs (::std::move (inner_attrs)), items (::std::move (items)) + {} + + // Copy constructor with vector clone + Crate (Crate const &other) + : has_utf8bom (other.has_utf8bom), has_shebang (other.has_shebang), + inner_attrs (other.inner_attrs) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + items.reserve (other.items.size ()); + + for (const auto &e : other.items) + { + items.push_back (e->clone_item ()); + } + } + + ~Crate () = default; + + // Overloaded assignment operator with vector clone + Crate &operator= (Crate const &other) + { + inner_attrs = other.inner_attrs; + has_shebang = other.has_shebang; + has_utf8bom = other.has_utf8bom; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + items.reserve (other.items.size ()); + + for (const auto &e : other.items) + { + items.push_back (e->clone_item ()); + } + + return *this; + } + + // Move constructors + Crate (Crate &&other) = default; + Crate &operator= (Crate &&other) = default; + + // Get crate representation as string (e.g. for debugging). + ::std::string as_string () const; +}; + +// Base path expression AST node - abstract +class PathExpr : public ExprWithoutBlock +{ +protected: + PathExpr (::std::vector<Attribute> outer_attribs) + : ExprWithoutBlock (::std::move (outer_attribs)) + {} + +public: + // TODO: think of a better and less hacky way to allow this + + // Replaces the outer attributes of this path expression with the given outer + // attributes. + void replace_outer_attrs (::std::vector<Attribute> outer_attrs) + { + set_outer_attrs (::std::move (outer_attrs)); + } +}; +} // namespace AST +} // namespace Rust #endif diff --git a/gcc/rust/ast/rust-cond-compilation.h b/gcc/rust/ast/rust-cond-compilation.h index 02353d3..ae6eb0a 100644 --- a/gcc/rust/ast/rust-cond-compilation.h +++ b/gcc/rust/ast/rust-cond-compilation.h @@ -5,196 +5,235 @@ #include "rust-ast.h" namespace Rust { - namespace AST { - // Base conditional compilation configuration predicate thing - abstract - class ConfigurationPredicate { - public: - virtual ~ConfigurationPredicate() {} - - // Unique pointer custom clone function - ::std::unique_ptr<ConfigurationPredicate> clone_configuration_predicate() const { - return ::std::unique_ptr<ConfigurationPredicate>( - clone_configuration_predicate_impl()); - } - - // not sure if I'll use this but here anyway - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function impl to be overriden in base classes - virtual ConfigurationPredicate* clone_configuration_predicate_impl() const = 0; - }; - - // A configuration option - true if option is set, false if option is not set. - class ConfigurationOption : public ConfigurationPredicate { - Identifier option_name; - - // bool has_string_literal_option_body; - ::std::string option_value; // technically a string or raw string literal - - public: - // Returns whether the configuration option has a "value" part of the key-value pair. - inline bool has_option_value() const { - return !option_value.empty(); - } - - // Key-value pair constructor - ConfigurationOption(Identifier option_name, ::std::string option_value) : - option_name(option_name), option_value(option_value) {} - - // Name-only constructor - ConfigurationOption(Identifier option_name) : option_name(option_name) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ConfigurationOption* clone_configuration_predicate_impl() const OVERRIDE { - return new ConfigurationOption(*this); - } - }; - - // TODO: inline - struct ConfigurationPredicateList { - ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > predicate_list; - }; - - // Predicate that returns true if all of the supplied predicates return true. - class ConfigurationAll : public ConfigurationPredicate { - ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > predicate_list; // inlined form - - public: - ConfigurationAll( - ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > predicate_list) : - predicate_list(predicate_list) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ConfigurationAll* clone_configuration_predicate_impl() const OVERRIDE { - return new ConfigurationAll(*this); - } - }; - - // Predicate that returns true if any of the supplied predicates are true. - class ConfigurationAny : public ConfigurationPredicate { - ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > predicate_list; // inlined form - - public: - ConfigurationAny( - ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > predicate_list) : - predicate_list(predicate_list) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ConfigurationAny* clone_configuration_predicate_impl() const OVERRIDE { - return new ConfigurationAny(*this); - } - }; - - // Predicate that produces the negation of a supplied other configuration predicate. - class ConfigurationNot : public ConfigurationPredicate { - ::std::unique_ptr<ConfigurationPredicate> config_to_negate; - - public: - ConfigurationNot(ConfigurationPredicate* config_to_negate) : - config_to_negate(config_to_negate) {} - - // Copy constructor with clone - ConfigurationNot(ConfigurationNot const& other) : - config_to_negate(other.config_to_negate->clone_configuration_predicate()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - ConfigurationNot& operator=(ConfigurationNot const& other) { - config_to_negate = other.config_to_negate->clone_configuration_predicate(); - - return *this; - } - - // move constructors - ConfigurationNot(ConfigurationNot&& other) = default; - ConfigurationNot& operator=(ConfigurationNot&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ConfigurationNot* clone_configuration_predicate_impl() const OVERRIDE { - return new ConfigurationNot(*this); - } - }; - - // TODO: relationship to other attributes? - class CfgAttribute { - ::std::unique_ptr<ConfigurationPredicate> config_to_include; - - public: - CfgAttribute(ConfigurationPredicate* config_to_include) : - config_to_include(config_to_include) {} - - // Copy constructor with clone - CfgAttribute(CfgAttribute const& other) : - config_to_include(other.config_to_include->clone_configuration_predicate()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - CfgAttribute& operator=(CfgAttribute const& other) { - config_to_include = other.config_to_include->clone_configuration_predicate(); - - return *this; - } - - // move constructors - CfgAttribute(CfgAttribute&& other) = default; - CfgAttribute& operator=(CfgAttribute&& other) = default; - }; - /* TODO: ok, best thing to do would be eliminating this class, making Attribute has a - * "is_cfg()" method, and having attribute path as "cfg" and AttrInput as - * ConfigurationPredicate (so make ConfigurationPredicate a subclass of AttrInput?). Would - * need special handling in parser, however. */ - - // TODO: inline - struct CfgAttrs { - ::std::vector<Attribute> cfg_attrs; - }; - - // TODO: relationship to other attributes? - class CfgAttrAttribute { - ::std::unique_ptr<ConfigurationPredicate> config_to_include; - ::std::vector<Attribute> cfg_attrs; - - public: - CfgAttrAttribute( - ConfigurationPredicate* config_to_include, ::std::vector<Attribute> cfg_attrs) : - config_to_include(config_to_include), - cfg_attrs(cfg_attrs) {} - - // Copy constructor with clone - CfgAttrAttribute(CfgAttrAttribute const& other) : - config_to_include(other.config_to_include->clone_configuration_predicate()), - cfg_attrs(cfg_attrs) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - CfgAttrAttribute& operator=(CfgAttrAttribute const& other) { - config_to_include = other.config_to_include->clone_configuration_predicate(); - cfg_attrs = other.cfg_attrs; - - return *this; - } - - // move constructors - CfgAttrAttribute(CfgAttrAttribute&& other) = default; - CfgAttrAttribute& operator=(CfgAttrAttribute&& other) = default; - }; - } -} - -#endif
\ No newline at end of file +namespace AST { +// Base conditional compilation configuration predicate thing - abstract +class ConfigurationPredicate +{ +public: + virtual ~ConfigurationPredicate () {} + + // Unique pointer custom clone function + ::std::unique_ptr<ConfigurationPredicate> + clone_configuration_predicate () const + { + return ::std::unique_ptr<ConfigurationPredicate> ( + clone_configuration_predicate_impl ()); + } + + // not sure if I'll use this but here anyway + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // Clone function impl to be overriden in base classes + virtual ConfigurationPredicate * + clone_configuration_predicate_impl () const = 0; +}; + +// A configuration option - true if option is set, false if option is not set. +class ConfigurationOption : public ConfigurationPredicate +{ + Identifier option_name; + + // bool has_string_literal_option_body; + ::std::string option_value; // technically a string or raw string literal + +public: + // Returns whether the configuration option has a "value" part of the + // key-value pair. + inline bool has_option_value () const { return !option_value.empty (); } + + // Key-value pair constructor + ConfigurationOption (Identifier option_name, ::std::string option_value) + : option_name (option_name), option_value (option_value) + {} + + // Name-only constructor + ConfigurationOption (Identifier option_name) : option_name (option_name) {} + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ConfigurationOption * + clone_configuration_predicate_impl () const OVERRIDE + { + return new ConfigurationOption (*this); + } +}; + +// TODO: inline +struct ConfigurationPredicateList +{ + ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > predicate_list; +}; + +// Predicate that returns true if all of the supplied predicates return true. +class ConfigurationAll : public ConfigurationPredicate +{ + ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > + predicate_list; // inlined form + +public: + ConfigurationAll ( + ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > predicate_list) + : predicate_list (predicate_list) + {} + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ConfigurationAll *clone_configuration_predicate_impl () const OVERRIDE + { + return new ConfigurationAll (*this); + } +}; + +// Predicate that returns true if any of the supplied predicates are true. +class ConfigurationAny : public ConfigurationPredicate +{ + ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > + predicate_list; // inlined form + +public: + ConfigurationAny ( + ::std::vector< ::std::unique_ptr<ConfigurationPredicate> > predicate_list) + : predicate_list (predicate_list) + {} + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ConfigurationAny *clone_configuration_predicate_impl () const OVERRIDE + { + return new ConfigurationAny (*this); + } +}; + +// Predicate that produces the negation of a supplied other configuration +// predicate. +class ConfigurationNot : public ConfigurationPredicate +{ + ::std::unique_ptr<ConfigurationPredicate> config_to_negate; + +public: + ConfigurationNot (ConfigurationPredicate *config_to_negate) + : config_to_negate (config_to_negate) + {} + + // Copy constructor with clone + ConfigurationNot (ConfigurationNot const &other) + : config_to_negate ( + other.config_to_negate->clone_configuration_predicate ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + ConfigurationNot &operator= (ConfigurationNot const &other) + { + config_to_negate = other.config_to_negate->clone_configuration_predicate (); + + return *this; + } + + // move constructors + ConfigurationNot (ConfigurationNot &&other) = default; + ConfigurationNot &operator= (ConfigurationNot &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ConfigurationNot *clone_configuration_predicate_impl () const OVERRIDE + { + return new ConfigurationNot (*this); + } +}; + +// TODO: relationship to other attributes? +class CfgAttribute +{ + ::std::unique_ptr<ConfigurationPredicate> config_to_include; + +public: + CfgAttribute (ConfigurationPredicate *config_to_include) + : config_to_include (config_to_include) + {} + + // Copy constructor with clone + CfgAttribute (CfgAttribute const &other) + : config_to_include ( + other.config_to_include->clone_configuration_predicate ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + CfgAttribute &operator= (CfgAttribute const &other) + { + config_to_include + = other.config_to_include->clone_configuration_predicate (); + + return *this; + } + + // move constructors + CfgAttribute (CfgAttribute &&other) = default; + CfgAttribute &operator= (CfgAttribute &&other) = default; +}; +/* TODO: ok, best thing to do would be eliminating this class, making Attribute + * has a "is_cfg()" method, and having attribute path as "cfg" and AttrInput as + * ConfigurationPredicate (so make ConfigurationPredicate a subclass of + * AttrInput?). Would need special handling in parser, however. */ + +// TODO: inline +struct CfgAttrs +{ + ::std::vector<Attribute> cfg_attrs; +}; + +// TODO: relationship to other attributes? +class CfgAttrAttribute +{ + ::std::unique_ptr<ConfigurationPredicate> config_to_include; + ::std::vector<Attribute> cfg_attrs; + +public: + CfgAttrAttribute (ConfigurationPredicate *config_to_include, + ::std::vector<Attribute> cfg_attrs) + : config_to_include (config_to_include), cfg_attrs (cfg_attrs) + {} + + // Copy constructor with clone + CfgAttrAttribute (CfgAttrAttribute const &other) + : config_to_include ( + other.config_to_include->clone_configuration_predicate ()), + cfg_attrs (cfg_attrs) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + CfgAttrAttribute &operator= (CfgAttrAttribute const &other) + { + config_to_include + = other.config_to_include->clone_configuration_predicate (); + cfg_attrs = other.cfg_attrs; + + return *this; + } + + // move constructors + CfgAttrAttribute (CfgAttrAttribute &&other) = default; + CfgAttrAttribute &operator= (CfgAttrAttribute &&other) = default; +}; +} // namespace AST +} // namespace Rust + +#endif diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index 992801f..2bc6cf9 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -5,4609 +5,5200 @@ #include "rust-path.h" namespace Rust { - namespace AST { - /* TODO: if GCC moves to C++17 or allows boost, replace some boolean "has_whatever" pairs with - * optional types (std::optional or boost::optional)? */ - - // forward decls: defined in rust-path.h, rust-type.h, rust-pattern.h, and rust-stmt.h - /*class PathInExpression; - class QualifiedPathInExpression; - class PathExprSegment;*/ // decls no longer required as "rust-path.h" is included - /*class Type; - class TypeNoBounds; - class Lifetime; - class Pattern; - class Statement;*/ // decls no longer required as definitions moved to rust-ast.h - - // Decl as definition moved to rust-ast.h - class ExprWithoutBlock; - - // AST node for an expression with an accompanying block - abstract - class ExprWithBlock : public Expr { - // TODO: should this mean that a BlockExpr should be a member variable? - protected: - ExprWithBlock(::std::vector<Attribute> outer_attrs = ::std::vector<Attribute>()) : - Expr(::std::move(outer_attrs)) {} - - // pure virtual clone implementation - virtual ExprWithBlock* clone_expr_with_block_impl() const = 0; - - // prevent having to define multiple clone expressions - virtual ExprWithBlock* clone_expr_impl() const OVERRIDE { - return clone_expr_with_block_impl(); - } - - public: - // Unique pointer custom clone function - ::std::unique_ptr<ExprWithBlock> clone_expr_with_block() const { - return ::std::unique_ptr<ExprWithBlock>(clone_expr_with_block_impl()); - } - }; - - // Literals? Or literal base? - class LiteralExpr : public ExprWithoutBlock { - /*public: - enum LitType { - CHAR, - STRING, - RAW_STRING, - BYTE, - BYTE_STRING, - RAW_BYTE_STRING, - INT, - FLOAT, - BOOL - }; - - private: - // TODO: maybe make subclasses of each type of literal with their typed values (or - // generics) - ::std::string value_as_string; - LitType type;*/ - // moved to Literal - Literal literal; - - Location locus; - - public: - ::std::string as_string() const { - return literal.as_string(); - } - - inline Literal::LitType get_lit_type() const { - return literal.get_lit_type(); - } - - LiteralExpr(::std::string value_as_string, Literal::LitType type, Location locus, - ::std::vector<Attribute> outer_attrs = ::std::vector<Attribute>()) : - ExprWithoutBlock(::std::move(outer_attrs)), - literal(::std::move(value_as_string), type), locus(locus) {} - - LiteralExpr(Literal literal, Location locus, - ::std::vector<Attribute> outer_attrs = ::std::vector<Attribute>()) : - ExprWithoutBlock(::std::move(outer_attrs)), - literal(::std::move(literal)), locus(locus) {} - - // Unique pointer custom clone function - ::std::unique_ptr<LiteralExpr> clone_literal_expr() const { - return ::std::unique_ptr<LiteralExpr>(clone_literal_expr_impl()); - } - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LiteralExpr* clone_expr_impl() const OVERRIDE { - return new LiteralExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual LiteralExpr* clone_expr_without_block_impl() const OVERRIDE { - return new LiteralExpr(*this); - } - - // not virtual as currently no subclasses of LiteralExpr, but could be in future - /*virtual*/ LiteralExpr* clone_literal_expr_impl() const { - return new LiteralExpr(*this); - } - }; - - // Literal expression attribute body (non-macro attribute) - class AttrInputLiteral : public AttrInput { - // Literal expression WITHOUT SUFFIX - // LiteralExpr* literal_expr; - //::std::unique_ptr<LiteralExpr> literal_expr; - LiteralExpr literal_expr; // as not using polymorphic behaviour, doesn't require pointer - // TODO: will require pointer if LiteralExpr is changed to have subclassing - - // TODO: should this store location data? - - public: - AttrInputLiteral(LiteralExpr lit_expr) : literal_expr(::std::move(lit_expr)) {} - /*~AttrInputLiteral() { - delete literal_expr; - }*/ - - ::std::string as_string() const { - return " = " + literal_expr.as_string(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // this can never be a cfg predicate - cfg and cfg_attr require a token-tree cfg - virtual bool check_cfg_predicate(const Session& session ATTRIBUTE_UNUSED) const OVERRIDE { - // TODO: ensure this is true - // DEBUG - fprintf( - stderr, "check_cfg_predicate call went to AttrInputLiteral - should not happen?\n"); - - return false; - } - - protected: - // Use covariance to implement clone function as returning an AttrInputLiteral object - virtual AttrInputLiteral* clone_attr_input_impl() const OVERRIDE { - return new AttrInputLiteral(*this); - } - }; - - // literal expr only meta item inner - TODO possibly replace with inheritance of LiteralExpr - // itself? - class MetaItemLitExpr : public MetaItemInner { - LiteralExpr lit_expr; - - public: - MetaItemLitExpr(LiteralExpr lit_expr) : lit_expr(::std::move(lit_expr)) {} - - ::std::string as_string() const OVERRIDE { - return lit_expr.as_string(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaItemLitExpr* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaItemLitExpr(*this); - } - }; - - // more generic meta item "path = lit" form - class MetaItemPathLit : public MetaItem { - SimplePath path; - LiteralExpr lit; - - public: - MetaItemPathLit(SimplePath path, LiteralExpr lit_expr) : - path(::std::move(path)), lit(::std::move(lit_expr)) {} - - ::std::string as_string() const OVERRIDE { - return path.as_string() + " = " + lit.as_string(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - // TODO: return true if "ident" is defined and value of it is "lit", return false - // otherwise - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaItemPathLit* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaItemPathLit(*this); - } - }; - - // AST node for a non-qualified path expression - FIXME: should this be inheritance instead? - /*class PathExprNonQual : public PathExpr { - PathInExpression path; - - public: - ::std::string as_string() const { - return path.as_string(); - } - - PathExprNonQual(PathInExpression path, ::std::vector<Attribute> outer_attribs) : - PathExpr(::std::move(outer_attribs)), path(::std::move(path)) {} - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual PathExprNonQual* clone_expr_impl() const OVERRIDE { - return new PathExprNonQual(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual PathExprNonQual* clone_expr_without_block_impl() const OVERRIDE { - return new PathExprNonQual(*this); - } - };*/ - // converted to inheritance - - // AST node for a qualified path expression - FIXME: should this be inheritance instead? - /*class PathExprQual : public PathExpr { - QualifiedPathInExpression path; - - public: - ::std::string as_string() const { - return path.as_string(); - } - - PathExprQual(QualifiedPathInExpression path, ::std::vector<Attribute> outer_attribs) : - PathExpr(::std::move(outer_attribs)), path(::std::move(path)) {} - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual PathExprQual* clone_expr_impl() const OVERRIDE { - return new PathExprQual(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual PathExprQual* clone_expr_without_block_impl() const OVERRIDE { - return new PathExprQual(*this); - } - };*/ - // replaced with inheritance - - // Represents an expression using unary or binary operators as AST node. Can be overloaded. - class OperatorExpr : public ExprWithoutBlock { - // TODO: create binary and unary operator subclasses? - - Location locus; - - protected: - // Variable must be protected to allow derived classes to use it as a first class citizen - // Expr* main_or_left_expr; - ::std::unique_ptr<Expr> main_or_left_expr; - - // Constructor (only for initialisation of expr purposes) - OperatorExpr(::std::unique_ptr<Expr> main_or_left_expr, - ::std::vector<Attribute> outer_attribs, Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - locus(locus), main_or_left_expr(::std::move(main_or_left_expr)) {} - - // Copy constructor (only for initialisation of expr purposes) - OperatorExpr(OperatorExpr const& other) : - ExprWithoutBlock(other), - locus(other.locus) /*, main_or_left_expr(other.main_or_left_expr->clone_expr())*/ { - // DEBUG: moved main_or_left_expr into body - move back later - - if (other.main_or_left_expr == NULL) { - fprintf(stderr, "other operator expr's main_or_left_expr is null!\n"); - } - - fprintf(stderr, - "called operator expr copy constructor - about to clone main_or_left_expr\n"); - main_or_left_expr = other.main_or_left_expr->clone_expr(); - fprintf(stderr, "successfully cloned main_or_left_expr\n"); - // this occurred successfully, so something else must be the issue - } - - // Overload assignment operator to deep copy expr - OperatorExpr& operator=(OperatorExpr const& other) { - ExprWithoutBlock::operator=(other); - main_or_left_expr = other.main_or_left_expr->clone_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - OperatorExpr(OperatorExpr&& other) = default; - OperatorExpr& operator=(OperatorExpr&& other) = default; - - public: - /*virtual ~OperatorExpr() { - delete main_or_left_expr; - }*/ - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - }; - - // Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be overloaded. - class BorrowExpr : public OperatorExpr { - bool is_mut; - bool double_borrow; - - public: - ::std::string as_string() const; - - BorrowExpr(::std::unique_ptr<Expr> borrow_lvalue, bool is_mut_borrow, - bool is_double_borrow, ::std::vector<Attribute> outer_attribs, Location locus) : - OperatorExpr(::std::move(borrow_lvalue), ::std::move(outer_attribs), locus), - is_mut(is_mut_borrow), double_borrow(is_double_borrow) {} - - // Copy constructor - define here if required - - // Destructor - define here if required - - // Overload assignment operator here if required - - // Move semantics here if required - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual BorrowExpr* clone_expr_impl() const OVERRIDE { - return new BorrowExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual BorrowExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on borrowexpr\n"); - - return new BorrowExpr(*this); - } - }; - - // Unary prefix * deference operator - class DereferenceExpr : public OperatorExpr { - public: - ::std::string as_string() const; - - // Constructor calls OperatorExpr's protected constructor - DereferenceExpr(::std::unique_ptr<Expr> deref_lvalue, - ::std::vector<Attribute> outer_attribs, Location locus) : - OperatorExpr(::std::move(deref_lvalue), ::std::move(outer_attribs), locus) {} - - // Copy constructor - define here if required - - // Destructor - define here if required - - // Overload assignment operator here if required - - // Move semantics here if required - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual DereferenceExpr* clone_expr_impl() const OVERRIDE { - return new DereferenceExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual DereferenceExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on dereferenceexpr\n"); - - return new DereferenceExpr(*this); - } - }; - - // Unary postfix ? error propogation operator. Cannot be overloaded. - class ErrorPropagationExpr : public OperatorExpr { - public: - ::std::string as_string() const; - - // Constructor calls OperatorExpr's protected constructor - ErrorPropagationExpr(::std::unique_ptr<Expr> potential_error_value, - ::std::vector<Attribute> outer_attribs, Location locus) : - OperatorExpr(::std::move(potential_error_value), ::std::move(outer_attribs), locus) {} - - // Copy constructor - define here if required - - // Destructor - define here if required - - // Overload assignment operator here if required - - // Move semantics here if required - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ErrorPropagationExpr* clone_expr_impl() const OVERRIDE { - return new ErrorPropagationExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ErrorPropagationExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on errorpropagationexpr\n"); - - return new ErrorPropagationExpr(*this); - } - }; - - // Unary prefix - or ! negation or NOT operators. - class NegationExpr : public OperatorExpr { - public: - enum NegationType { NEGATE, NOT }; - - private: - // Note: overload negation via std::ops::Neg and not via std::ops::Not - // Negation only works for signed integer and floating-point types, NOT only works for - // boolean and integer types (via bitwise NOT) - NegationType negation_type; - - public: - ::std::string as_string() const; - - inline NegationType get_negation_type() const { - return negation_type; - } - - // Constructor calls OperatorExpr's protected constructor - NegationExpr(::std::unique_ptr<Expr> negated_value, NegationType negation_kind, - ::std::vector<Attribute> outer_attribs, Location locus) : - OperatorExpr(::std::move(negated_value), ::std::move(outer_attribs), locus), - negation_type(negation_kind) {} - - // Copy constructor - define here if required - - // Destructor - define here if required - - // Overload assignment operator here if required - - // Move semantics here if required - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual NegationExpr* clone_expr_impl() const OVERRIDE { - return new NegationExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual NegationExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on negationexpr\n"); - - return new NegationExpr(*this); - } - }; - - // Infix binary operators. +, -, *, /, %, &, |, ^, <<, >> - class ArithmeticOrLogicalExpr : public OperatorExpr { - public: - enum ExprType { - ADD, // std::ops::Add - SUBTRACT, // std::ops::Sub - MULTIPLY, // std::ops::Mul - DIVIDE, // std::ops::Div - MODULUS, // std::ops::Rem - BITWISE_AND, // std::ops::BitAnd - BITWISE_OR, // std::ops::BitOr - BITWISE_XOR, // std::ops::BitXor - LEFT_SHIFT, // std::ops::Shl - RIGHT_SHIFT // std::ops::Shr - }; - - private: - // Note: overloading trait specified in comments - ExprType expr_type; - - // Expr* right_expr; - ::std::unique_ptr<Expr> right_expr; - - public: - /*~ArithmeticOrLogicalExpr() { - delete right_expr; - }*/ - - ::std::string as_string() const; - - inline ExprType get_expr_type() const { - return expr_type; - } - - // Constructor calls OperatorExpr's protected constructor - ArithmeticOrLogicalExpr(::std::unique_ptr<Expr> left_value, - ::std::unique_ptr<Expr> right_value, ExprType expr_kind, Location locus) : - OperatorExpr(::std::move(left_value), ::std::vector<Attribute>(), locus), - expr_type(expr_kind), right_expr(::std::move(right_value)) {} - // outer attributes not allowed - - // Copy constructor - probably required due to unique pointer - ArithmeticOrLogicalExpr(ArithmeticOrLogicalExpr const& other) : - OperatorExpr(other), expr_type(other.expr_type), - right_expr(other.right_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator - ArithmeticOrLogicalExpr& operator=(ArithmeticOrLogicalExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - expr_type = other.expr_type; - - return *this; - } - - // move constructors - ArithmeticOrLogicalExpr(ArithmeticOrLogicalExpr&& other) = default; - ArithmeticOrLogicalExpr& operator=(ArithmeticOrLogicalExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ArithmeticOrLogicalExpr* clone_expr_impl() const OVERRIDE { - return new ArithmeticOrLogicalExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ArithmeticOrLogicalExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf( - stderr, "called clone_expr_without_block_impl() on arithmeticorlogicalexpr\n"); - - return new ArithmeticOrLogicalExpr(*this); - } - }; - - // Infix binary comparison operators. ==, !=, <, <=, >, >= - class ComparisonExpr : public OperatorExpr { - public: - enum ExprType { - EQUAL, // std::cmp::PartialEq::eq - NOT_EQUAL, // std::cmp::PartialEq::ne - GREATER_THAN, // std::cmp::PartialEq::gt - LESS_THAN, // std::cmp::PartialEq::lt - GREATER_OR_EQUAL, // std::cmp::PartialEq::ge - LESS_OR_EQUAL // std::cmp::PartialEq::le - }; - - private: - // Note: overloading trait specified in comments - ExprType expr_type; - - // Expr* right_expr; - ::std::unique_ptr<Expr> right_expr; - - public: - /*~ComparisonExpr() { - delete right_expr; - }*/ - - ::std::string as_string() const; - - inline ExprType get_expr_type() const { - return expr_type; - } - - // Constructor requires pointers for polymorphism - ComparisonExpr(::std::unique_ptr<Expr> left_value, ::std::unique_ptr<Expr> right_value, - ExprType comparison_kind, Location locus) : - OperatorExpr(::std::move(left_value), ::std::vector<Attribute>(), locus), - expr_type(comparison_kind), right_expr(::std::move(right_value)) {} - // outer attributes not allowed - - // Copy constructor also calls OperatorExpr's protected constructor - ComparisonExpr(ComparisonExpr const& other) : - OperatorExpr(other), expr_type(other.expr_type), - right_expr(other.right_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to deep copy - ComparisonExpr& operator=(ComparisonExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - expr_type = other.expr_type; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ComparisonExpr(ComparisonExpr&& other) = default; - ComparisonExpr& operator=(ComparisonExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2) maybe? - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ComparisonExpr* clone_expr_impl() const OVERRIDE { - return new ComparisonExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ComparisonExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on comparisonexpr\n"); - - return new ComparisonExpr(*this); - } - }; - - // Infix binary lazy boolean logical operators && and ||. - class LazyBooleanExpr : public OperatorExpr { - public: - enum ExprType { LOGICAL_OR, LOGICAL_AND }; - - private: - ExprType expr_type; - - // Expr* right_expr; - ::std::unique_ptr<Expr> right_expr; - - public: - /*~LazyBooleanExpr() { - delete right_expr; - }*/ - - // Constructor calls OperatorExpr's protected constructor - LazyBooleanExpr(::std::unique_ptr<Expr> left_bool_expr, - ::std::unique_ptr<Expr> right_bool_expr, ExprType expr_kind, Location locus) : - OperatorExpr(::std::move(left_bool_expr), ::std::vector<Attribute>(), locus), - expr_type(expr_kind), right_expr(::std::move(right_bool_expr)) {} - // outer attributes not allowed - - // Copy constructor also calls OperatorExpr's protected constructor - LazyBooleanExpr(LazyBooleanExpr const& other) : - OperatorExpr(other), expr_type(other.expr_type), - right_expr(other.right_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to deep copy - LazyBooleanExpr& operator=(LazyBooleanExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - expr_type = other.expr_type; - - return *this; - } - - // move constructors - LazyBooleanExpr(LazyBooleanExpr&& other) = default; - LazyBooleanExpr& operator=(LazyBooleanExpr&& other) = default; - - ::std::string as_string() const; - - inline ExprType get_expr_type() const { - return expr_type; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LazyBooleanExpr* clone_expr_impl() const OVERRIDE { - return new LazyBooleanExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual LazyBooleanExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on lazybooleanexpr\n"); - - return new LazyBooleanExpr(*this); - } - }; - - // Binary infix "as" cast expression. - class TypeCastExpr : public OperatorExpr { - // TypeNoBounds type_to_convert_to; - ::std::unique_ptr<TypeNoBounds> type_to_convert_to; - - // Note: only certain type casts allowed, outlined in reference - public: - ::std::string as_string() const; - - // Constructor requires calling protected constructor of OperatorExpr - TypeCastExpr(::std::unique_ptr<Expr> expr_to_cast, - ::std::unique_ptr<TypeNoBounds> type_to_cast_to, Location locus) : - OperatorExpr(::std::move(expr_to_cast), ::std::vector<Attribute>(), locus), - type_to_convert_to(::std::move(type_to_cast_to)) {} - // outer attributes not allowed - - // Copy constructor also requires calling protected constructor - TypeCastExpr(TypeCastExpr const& other) : - OperatorExpr(other), - type_to_convert_to(other.type_to_convert_to->clone_type_no_bounds()) {} - - // Destructor - define here if required - - // Overload assignment operator to deep copy - TypeCastExpr& operator=(TypeCastExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - type_to_convert_to = other.type_to_convert_to->clone_type_no_bounds(); - - return *this; - } - - // move constructors as not supported in c++03 - TypeCastExpr(TypeCastExpr&& other) = default; - TypeCastExpr& operator=(TypeCastExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TypeCastExpr* clone_expr_impl() const OVERRIDE { - return new TypeCastExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TypeCastExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on typecastexpr\n"); - - return new TypeCastExpr(*this); - } - }; - - // Binary assignment expression. - class AssignmentExpr : public OperatorExpr { - // Expr* right_expr; - ::std::unique_ptr<Expr> right_expr; - - public: - /*~AssignmentExpr() { - delete right_expr; - }*/ - - ::std::string as_string() const; - - // Call OperatorExpr constructor to initialise left_expr - AssignmentExpr(::std::unique_ptr<Expr> value_to_assign_to, - ::std::unique_ptr<Expr> value_to_assign, Location locus) : - OperatorExpr(::std::move(value_to_assign_to), ::std::vector<Attribute>(), locus), - right_expr(::std::move(value_to_assign)) {} - // outer attributes not allowed - - // Call OperatorExpr constructor in copy constructor, as well as clone - AssignmentExpr(AssignmentExpr const& other) : - OperatorExpr(other) /*, right_expr(other.right_expr->clone_expr())*/ { - // DEBUG: moved cloning right expr into body - fprintf(stderr, - "assignment expr copy constructor successfully cloned base operator expr\n"); - if (other.right_expr == NULL) { - fprintf(stderr, "other expr's right expr (in assignment) is null!!!"); - } - fprintf(stderr, "test other's right expr as string: %s\n", - other.right_expr->as_string().c_str()); - // apparently, despite not being null, cloning still fails - right_expr = other.right_expr->clone_expr(); - fprintf(stderr, "assignment expr copy constructor successfully cloned right expr\n"); - - // DEBUG - fprintf(stderr, "assignment expr copy constructor called successfully\n"); - } - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr right_expr - AssignmentExpr& operator=(AssignmentExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - AssignmentExpr(AssignmentExpr&& other) = default; - AssignmentExpr& operator=(AssignmentExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual AssignmentExpr* clone_expr_impl() const OVERRIDE { - return new AssignmentExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual AssignmentExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on assignmentexpr\n"); - - return new AssignmentExpr(*this); - } - }; - - // Binary infix compound assignment (arithmetic or logic then assignment) expressions. - class CompoundAssignmentExpr : public OperatorExpr { - public: - enum ExprType { - ADD, // std::ops::AddAssign - SUBTRACT, // std::ops::SubAssign - MULTIPLY, // std::ops::MulAssign - DIVIDE, // std::ops::DivAssign - MODULUS, // std::ops::RemAssign - BITWISE_AND, // std::ops::BitAndAssign - BITWISE_OR, // std::ops::BitOrAssign - BITWISE_XOR, // std::ops::BitXorAssign - LEFT_SHIFT, // std::ops::ShlAssign - RIGHT_SHIFT // std::ops::ShrAssign - }; - - private: - // Note: overloading trait specified in comments - ExprType expr_type; - - // Expr* right_expr; - ::std::unique_ptr<Expr> right_expr; - - public: - /*~CompoundAssignmentExpr() { - delete right_expr; - }*/ - - ::std::string as_string() const; - - inline ExprType get_expr_type() const { - return expr_type; - } - - // Use pointers in constructor to enable polymorphism - CompoundAssignmentExpr(::std::unique_ptr<Expr> value_to_assign_to, - ::std::unique_ptr<Expr> value_to_assign, ExprType expr_kind, Location locus) : - OperatorExpr(::std::move(value_to_assign_to), ::std::vector<Attribute>(), locus), - expr_type(expr_kind), right_expr(::std::move(value_to_assign)) {} - // outer attributes not allowed - - // Have clone in copy constructor - CompoundAssignmentExpr(CompoundAssignmentExpr const& other) : - OperatorExpr(other), expr_type(other.expr_type), - right_expr(other.right_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - CompoundAssignmentExpr& operator=(CompoundAssignmentExpr const& other) { - OperatorExpr::operator=(other); - // main_or_left_expr = other.main_or_left_expr->clone_expr(); - right_expr = other.right_expr->clone_expr(); - expr_type = other.expr_type; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - CompoundAssignmentExpr(CompoundAssignmentExpr&& other) = default; - CompoundAssignmentExpr& operator=(CompoundAssignmentExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual CompoundAssignmentExpr* clone_expr_impl() const OVERRIDE { - return new CompoundAssignmentExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual CompoundAssignmentExpr* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called clone_expr_without_block_impl() on compoundassignmentexpr\n"); - - return new CompoundAssignmentExpr(*this); - } - }; - - // Expression in parentheses (i.e. like literally just any 3 + (2 * 6)) - class GroupedExpr : public ExprWithoutBlock { - ::std::vector<Attribute> inner_attrs; - // Expr* expr_in_parens; - ::std::unique_ptr<Expr> expr_in_parens; - - Location locus; - - public: - /*~GroupedExpr() { - delete expr_in_parens; - }*/ - - ::std::string as_string() const; - - inline ::std::vector<Attribute> get_inner_attrs() const { - return inner_attrs; - } - - GroupedExpr(::std::unique_ptr<Expr> parenthesised_expr, - ::std::vector<Attribute> inner_attribs, ::std::vector<Attribute> outer_attribs, - Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), - expr_in_parens(::std::move(parenthesised_expr)), locus(locus) {} - - // Copy constructor includes clone for expr_in_parens - GroupedExpr(GroupedExpr const& other) : - ExprWithoutBlock(other), inner_attrs(other.inner_attrs), - expr_in_parens(other.expr_in_parens->clone_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone expr_in_parens - GroupedExpr& operator=(GroupedExpr const& other) { - ExprWithoutBlock::operator=(other); - inner_attrs = other.inner_attrs; - expr_in_parens = other.expr_in_parens->clone_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - GroupedExpr(GroupedExpr&& other) = default; - GroupedExpr& operator=(GroupedExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual GroupedExpr* clone_expr_impl() const OVERRIDE { - return new GroupedExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual GroupedExpr* clone_expr_without_block_impl() const OVERRIDE { - return new GroupedExpr(*this); - } - }; - - // Base array initialisation internal element representation thing (abstract) - // aka ArrayElements - class ArrayElems { - public: - virtual ~ArrayElems() {} - - // Unique pointer custom clone ArrayElems function - ::std::unique_ptr<ArrayElems> clone_array_elems() const { - return ::std::unique_ptr<ArrayElems>(clone_array_elems_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual ArrayElems* clone_array_elems_impl() const = 0; - }; - - // Value array elements - class ArrayElemsValues : public ArrayElems { - //::std::vector<Expr> values; - ::std::vector< ::std::unique_ptr<Expr> > values; - - // TODO: should this store location data? - - public: - /*inline ::std::vector< ::std::unique_ptr<Expr> > get_values() const { - return values; - }*/ - - ArrayElemsValues(::std::vector< ::std::unique_ptr<Expr> > elems) : - values(::std::move(elems)) {} - - // copy constructor with vector clone - ArrayElemsValues(ArrayElemsValues const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - values.reserve(other.values.size()); - - for (const auto& e : other.values) { - values.push_back(e->clone_expr()); - } - } - - // overloaded assignment operator with vector clone - ArrayElemsValues& operator=(ArrayElemsValues const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - values.reserve(other.values.size()); - - for (const auto& e : other.values) { - values.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - ArrayElemsValues(ArrayElemsValues&& other) = default; - ArrayElemsValues& operator=(ArrayElemsValues&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - virtual ArrayElemsValues* clone_array_elems_impl() const OVERRIDE { - return new ArrayElemsValues(*this); - } - }; - - // Copied array element and number of copies - class ArrayElemsCopied : public ArrayElems { - // Expr* elem_to_copy; - ::std::unique_ptr<Expr> elem_to_copy; - // Expr* num_copies; - ::std::unique_ptr<Expr> num_copies; - - // TODO: should this store location data? - - public: - /*~ArrayElemsCopied() { - delete num_copies; - delete elem_to_copy; - }*/ - - // Constructor requires pointers for polymorphism - ArrayElemsCopied( - ::std::unique_ptr<Expr> copied_elem, ::std::unique_ptr<Expr> copy_amount) : - elem_to_copy(::std::move(copied_elem)), - num_copies(::std::move(copy_amount)) {} - - // Copy constructor required due to unique_ptr - uses custom clone - ArrayElemsCopied(ArrayElemsCopied const& other) : - elem_to_copy(other.elem_to_copy->clone_expr()), - num_copies(other.num_copies->clone_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator for deep copying - ArrayElemsCopied& operator=(ArrayElemsCopied const& other) { - elem_to_copy = other.elem_to_copy->clone_expr(); - num_copies = other.num_copies->clone_expr(); - - return *this; - } - - // move constructors - ArrayElemsCopied(ArrayElemsCopied&& other) = default; - ArrayElemsCopied& operator=(ArrayElemsCopied&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - virtual ArrayElemsCopied* clone_array_elems_impl() const OVERRIDE { - return new ArrayElemsCopied(*this); - } - }; - - // Array definition-ish expression - class ArrayExpr : public ExprWithoutBlock { - ::std::vector<Attribute> inner_attrs; - // ArrayElems internal_elements; - ::std::unique_ptr<ArrayElems> internal_elements; - - Location locus; - - public: - ::std::string as_string() const; - - inline ::std::vector<Attribute> get_inner_attrs() const { - return inner_attrs; - } - - // Returns whether array expr has array elems or if it is just empty. - inline bool has_array_elems() const { - return internal_elements != NULL; - } - - // Constructor requires ArrayElems pointer - ArrayExpr(::std::unique_ptr<ArrayElems> array_elems, - ::std::vector<Attribute> inner_attribs, ::std::vector<Attribute> outer_attribs, - Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), internal_elements(::std::move(array_elems)), - locus(locus) {} - - // Copy constructor requires cloning ArrayElems for polymorphism to hold - ArrayExpr(ArrayExpr const& other) : - ExprWithoutBlock(other), inner_attrs(other.inner_attrs), locus(other.locus) { - if (other.has_array_elems()) { - internal_elements = other.internal_elements->clone_array_elems(); - } - } - - // Destructor - define here if required - - // Overload assignment operator to clone internal_elements - ArrayExpr& operator=(ArrayExpr const& other) { - ExprWithoutBlock::operator=(other); - inner_attrs = other.inner_attrs; - if (other.has_array_elems()) { - internal_elements = other.internal_elements->clone_array_elems(); - } - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ArrayExpr(ArrayExpr&& other) = default; - ArrayExpr& operator=(ArrayExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayExpr* clone_expr_impl() const OVERRIDE { - return new ArrayExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayExpr* clone_expr_without_block_impl() const OVERRIDE { - return new ArrayExpr(*this); - } - }; - - // Aka IndexExpr (also applies to slices) - // Apparently a[b] is equivalent to *std::ops::Index::index(&a, b) or - // *std::ops::Index::index_mut(&mut a, b) - // Also apparently deref operations on a will be repeatedly applied to find an implementation - class ArrayIndexExpr : public ExprWithoutBlock { - /*Expr* array_expr; - Expr* index_expr;*/ - ::std::unique_ptr<Expr> array_expr; - ::std::unique_ptr<Expr> index_expr; - - Location locus; - - public: - /*~ArrayIndexExpr() { - delete index_expr; - delete array_expr; - }*/ - - ::std::string as_string() const; - - ArrayIndexExpr(::std::unique_ptr<Expr> array_expr, - ::std::unique_ptr<Expr> array_index_expr, ::std::vector<Attribute> outer_attribs, - Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - array_expr(::std::move(array_expr)), index_expr(::std::move(array_index_expr)), - locus(locus) {} - - // Copy constructor requires special cloning due to unique_ptr - ArrayIndexExpr(ArrayIndexExpr const& other) : - ExprWithoutBlock(other), array_expr(other.array_expr->clone_expr()), - index_expr(other.index_expr->clone_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptrs - ArrayIndexExpr& operator=(ArrayIndexExpr const& other) { - ExprWithoutBlock::operator=(other); - array_expr = other.array_expr->clone_expr(); - index_expr = other.index_expr->clone_expr(); - // outer_attrs = other.outer_attrs; - locus = other.locus; - - return *this; - } - - // move constructors - ArrayIndexExpr(ArrayIndexExpr&& other) = default; - ArrayIndexExpr& operator=(ArrayIndexExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayIndexExpr* clone_expr_impl() const OVERRIDE { - return new ArrayIndexExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayIndexExpr* clone_expr_without_block_impl() const OVERRIDE { - return new ArrayIndexExpr(*this); - } - }; - - // AST representation of a tuple - class TupleExpr : public ExprWithoutBlock { - ::std::vector<Attribute> inner_attrs; - - //::std::vector<Expr> tuple_elems; - ::std::vector< ::std::unique_ptr<Expr> > tuple_elems; - // replaces (inlined version of) TupleElements - - Location locus; - - public: - ::std::string as_string() const; - - inline ::std::vector<Attribute> get_inner_attrs() const { - return inner_attrs; - } - - TupleExpr(::std::vector< ::std::unique_ptr<Expr> > tuple_elements, - ::std::vector<Attribute> inner_attribs, ::std::vector<Attribute> outer_attribs, - Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), tuple_elems(::std::move(tuple_elements)), - locus(locus) {} - - // copy constructor with vector clone - TupleExpr(TupleExpr const& other) : - ExprWithoutBlock(other), inner_attrs(other.inner_attrs), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - tuple_elems.reserve(other.tuple_elems.size()); - - for (const auto& e : other.tuple_elems) { - tuple_elems.push_back(e->clone_expr()); - } - } - - // overloaded assignment operator to vector clone - TupleExpr& operator=(TupleExpr const& other) { - ExprWithoutBlock::operator=(other); - inner_attrs = other.inner_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - tuple_elems.reserve(other.tuple_elems.size()); - - for (const auto& e : other.tuple_elems) { - tuple_elems.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - TupleExpr(TupleExpr&& other) = default; - TupleExpr& operator=(TupleExpr&& other) = default; - - // Note: syntactically, can disambiguate single-element tuple from parens with comma, i.e. - // (0,) rather than (0) - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleExpr* clone_expr_impl() const OVERRIDE { - return new TupleExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TupleExpr* clone_expr_without_block_impl() const OVERRIDE { - return new TupleExpr(*this); - } - }; - - // aka TupleIndexingExpr - // AST representation of a tuple indexing expression - class TupleIndexExpr : public ExprWithoutBlock { - // Expr* tuple_expr; - ::std::unique_ptr<Expr> tuple_expr; - // TupleIndex is a decimal int literal with no underscores or suffix - TupleIndex tuple_index; - - Location locus; - - // i.e. pair.0 - - public: - /*~TupleIndexExpr() { - delete tuple_expr; - }*/ - - ::std::string as_string() const; - - inline TupleIndex get_tuple_index() const { - return tuple_index; - } - - TupleIndexExpr(::std::unique_ptr<Expr> tuple_expr, TupleIndex index, - ::std::vector<Attribute> outer_attribs, Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - tuple_expr(::std::move(tuple_expr)), tuple_index(index), locus(locus) {} - - // Copy constructor requires a clone for tuple_expr - TupleIndexExpr(TupleIndexExpr const& other) : - ExprWithoutBlock(other), tuple_expr(other.tuple_expr->clone_expr()), - tuple_index(other.tuple_index), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator in order to clone - TupleIndexExpr& operator=(TupleIndexExpr const& other) { - ExprWithoutBlock::operator=(other); - tuple_expr = other.tuple_expr->clone_expr(); - tuple_index = other.tuple_index; - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - TupleIndexExpr(TupleIndexExpr&& other) = default; - TupleIndexExpr& operator=(TupleIndexExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleIndexExpr* clone_expr_impl() const OVERRIDE { - return new TupleIndexExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TupleIndexExpr* clone_expr_without_block_impl() const OVERRIDE { - return new TupleIndexExpr(*this); - } - }; - - // Base struct/tuple/union value creator AST node (abstract) - class StructExpr : public ExprWithoutBlock { - PathInExpression struct_name; - - protected: - // Protected constructor to allow initialising struct_name - StructExpr(PathInExpression struct_path, ::std::vector<Attribute> outer_attribs) : - ExprWithoutBlock(::std::move(outer_attribs)), struct_name(::std::move(struct_path)) {} - - public: - inline const PathInExpression& get_struct_name() const { - return struct_name; - } - - virtual ::std::string as_string() const; - }; - - // Actual AST node of the struct creator (with no fields). Not abstract! - class StructExprStruct : public StructExpr { - ::std::vector<Attribute> inner_attrs; - - Location locus; - - public: - ::std::string as_string() const; - - inline ::std::vector<Attribute> get_inner_attrs() const { - return inner_attrs; - } - - // Constructor has to call protected constructor of base class - StructExprStruct(PathInExpression struct_path, ::std::vector<Attribute> inner_attribs, - ::std::vector<Attribute> outer_attribs, Location locus) : - StructExpr(::std::move(struct_path), ::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), locus(locus) {} - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStruct* clone_expr_impl() const OVERRIDE { - return new StructExprStruct(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStruct* clone_expr_without_block_impl() const OVERRIDE { - return new StructExprStruct(*this); - } - }; - - // AST node representing expression used to fill a struct's fields from another struct - struct StructBase { - private: - // Expr* base_struct; - ::std::unique_ptr<Expr> base_struct; - - // TODO: should this store location data? - - public: - StructBase(::std::unique_ptr<Expr> base_struct_ptr) : - base_struct(::std::move(base_struct_ptr)) {} - - // Copy constructor requires clone - StructBase(StructBase const& other) { - // HACK: gets around base_struct pointer being null (e.g. if no struct base exists) - if (other.base_struct != NULL) { - other.base_struct->clone_expr(); - } - - // DEBUG: - fprintf(stderr, "struct base copy constructor called successfully\n"); - } - - // Destructor - ~StructBase() = default; - - // Overload assignment operator to clone base_struct - StructBase& operator=(StructBase const& other) { - base_struct = other.base_struct->clone_expr(); - - return *this; - } - - // move constructors - StructBase(StructBase&& other) = default; - StructBase& operator=(StructBase&& other) = default; - - /*~StructBase() { - delete base_struct; - }*/ - - // Returns a null expr-ed StructBase - error state - static StructBase error() { - return StructBase(NULL); - } - - // Returns whether StructBase is in error state - inline bool is_invalid() const { - return base_struct == NULL; - } - - ::std::string as_string() const; - }; - - // Base AST node for a single struct expression field (in struct instance creation) - abstract - class StructExprField { - public: - virtual ~StructExprField() {} - - // Unique pointer custom clone function - ::std::unique_ptr<StructExprField> clone_struct_expr_field() const { - return ::std::unique_ptr<StructExprField>(clone_struct_expr_field_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual StructExprField* clone_struct_expr_field_impl() const = 0; - }; - - // Identifier-only variant of StructExprField AST node - class StructExprFieldIdentifier : public StructExprField { - Identifier field_name; - - // TODO: should this store location data? - - public: - StructExprFieldIdentifier(Identifier field_identifier) : - field_name(::std::move(field_identifier)) {} - - ::std::string as_string() const { - return field_name; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this rather than base - virtual StructExprFieldIdentifier* clone_struct_expr_field_impl() const OVERRIDE { - return new StructExprFieldIdentifier(*this); - } - }; - - // Base AST node for a single struct expression field with an assigned value - abstract - class StructExprFieldWithVal : public StructExprField { - // Expr* value; - ::std::unique_ptr<Expr> value; - - protected: - StructExprFieldWithVal(::std::unique_ptr<Expr> field_value) : - value(::std::move(field_value)) {} - - // Copy constructor requires clone - StructExprFieldWithVal(StructExprFieldWithVal const& other) : - value(other.value->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr - StructExprFieldWithVal& operator=(StructExprFieldWithVal const& other) { - value = other.value->clone_expr(); - - return *this; - } - - // move constructors - StructExprFieldWithVal(StructExprFieldWithVal&& other) = default; - StructExprFieldWithVal& operator=(StructExprFieldWithVal&& other) = default; - - public: - /*~StructExprFieldWithVal() { - delete value; - }*/ - - ::std::string as_string() const; - }; - - // Identifier and value variant of StructExprField AST node - class StructExprFieldIdentifierValue : public StructExprFieldWithVal { - Identifier field_name; - - // TODO: should this store location data? - - public: - StructExprFieldIdentifierValue( - Identifier field_identifier, ::std::unique_ptr<Expr> field_value) : - StructExprFieldWithVal(::std::move(field_value)), - field_name(::std::move(field_identifier)) {} - - // copy constructor, destructor, and overloaded assignment operator should carry through - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this rather than base - virtual StructExprFieldIdentifierValue* clone_struct_expr_field_impl() const OVERRIDE { - return new StructExprFieldIdentifierValue(*this); - } - }; - - // Tuple index and value variant of StructExprField AST node - class StructExprFieldIndexValue : public StructExprFieldWithVal { - TupleIndex index; - - // TODO: should this store location data? - - public: - StructExprFieldIndexValue(TupleIndex tuple_index, ::std::unique_ptr<Expr> field_value) : - StructExprFieldWithVal(::std::move(field_value)), index(tuple_index) {} - - // copy constructor, destructor, and overloaded assignment operator should carry through - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this rather than base - virtual StructExprFieldIndexValue* clone_struct_expr_field_impl() const OVERRIDE { - return new StructExprFieldIndexValue(*this); - } - }; - - // AST node of a struct creator with fields - class StructExprStructFields : public StructExprStruct { - //::std::vector<StructExprField> fields; - ::std::vector< ::std::unique_ptr<StructExprField> > fields; - - // bool has_struct_base; - StructBase struct_base; - - public: - ::std::string as_string() const; - - inline bool has_struct_base() const { - return !struct_base.is_invalid(); - } - - /*inline ::std::vector< ::std::unique_ptr<StructExprField> > get_fields() const { - return fields; - }*/ - - /*inline StructBase get_struct_base() const { - return has_struct_base ? struct_base : StructBase::error(); - }*/ - - // Constructor for StructExprStructFields when no struct base is used - StructExprStructFields(PathInExpression struct_path, - ::std::vector< ::std::unique_ptr<StructExprField> > expr_fields, Location locus, - StructBase base_struct = StructBase::error(), - ::std::vector<Attribute> inner_attribs = ::std::vector<Attribute>(), - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - StructExprStruct(::std::move(struct_path), ::std::move(inner_attribs), - ::std::move(outer_attribs), locus), - fields(::std::move(expr_fields)), struct_base(::std::move(base_struct)) {} - - // copy constructor with vector clone - StructExprStructFields(StructExprStructFields const& other) : - StructExprStruct(other), struct_base(other.struct_base) { - // DEBUG - fprintf(stderr, "got past the initialisation list part of copy constructor\n"); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - // DEBUG - fprintf(stderr, "reserved space in fields\n"); - - for (const auto& e : other.fields) { - // DEBUG - fprintf(stderr, "about to clone a field\n"); - - fields.push_back(e->clone_struct_expr_field()); - - // DEBUG - fprintf(stderr, "cloned a field successfully\n"); - } - - // DEBUG - fprintf(stderr, "finished cloning fields\n"); - } - - // overloaded assignment operator with vector clone - StructExprStructFields& operator=(StructExprStructFields const& other) { - StructExprStruct::operator=(other); - struct_base = other.struct_base; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_struct_expr_field()); - } - - return *this; - } - - // move constructors - StructExprStructFields(StructExprStructFields&& other) = default; - StructExprStructFields& operator=(StructExprStructFields&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStructFields* clone_expr_impl() const OVERRIDE { - return new StructExprStructFields(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStructFields* clone_expr_without_block_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "called structexprstructfields clone expr without block impl - about " - "to return new structexprstructfields\n"); - - // DEBUG - test creation of a base from this - fprintf(stderr, "about to try to create and allocate structexprstruct \n"); - StructExprStruct* test_DELETE = new StructExprStruct(*this); - delete test_DELETE; - fprintf(stderr, "managed to create and allocate structexprstruct \n"); - // very weird: can create and allocate structexpstruct but not structexprstructfields - - // DEBUG - test creation of a non-returned class from this - fprintf(stderr, - "about to try to create and allocate structexprstructfields (but not return)\n"); - StructExprStructFields* test_DELETE2 = new StructExprStructFields(*this); - delete test_DELETE2; - fprintf(stderr, - "managed to create and allocate structexprstructfields (if not returned) \n"); - // ok this fails. fair enough. - - return new StructExprStructFields(*this); - } - }; - - // AST node of the functional update struct creator - class StructExprStructBase : public StructExprStruct { - StructBase struct_base; - - public: - ::std::string as_string() const; - - /*inline StructBase get_struct_base() const { - return struct_base; - }*/ - - StructExprStructBase(PathInExpression struct_path, StructBase base_struct, - ::std::vector<Attribute> inner_attribs, ::std::vector<Attribute> outer_attribs, - Location locus) : - StructExprStruct(::std::move(struct_path), ::std::move(inner_attribs), - ::std::move(outer_attribs), locus), - struct_base(::std::move(base_struct)) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStructBase* clone_expr_impl() const OVERRIDE { - return new StructExprStructBase(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprStructBase* clone_expr_without_block_impl() const OVERRIDE { - return new StructExprStructBase(*this); - } - }; - - // AST node of a tuple struct creator - class StructExprTuple : public StructExpr { - ::std::vector<Attribute> inner_attrs; - //::std::vector<Expr> exprs; - ::std::vector< ::std::unique_ptr<Expr> > exprs; - - Location locus; - - public: - ::std::string as_string() const; - - inline const ::std::vector<Attribute>& get_inner_attrs() const { - return inner_attrs; - } - - /*inline ::std::vector< ::std::unique_ptr<Expr> > get_exprs() const { - return exprs; - }*/ - - StructExprTuple(PathInExpression struct_path, - ::std::vector< ::std::unique_ptr<Expr> > tuple_exprs, - ::std::vector<Attribute> inner_attribs, ::std::vector<Attribute> outer_attribs, - Location locus) : - StructExpr(::std::move(struct_path), ::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), exprs(::std::move(tuple_exprs)), locus(locus) { - } - - // copy constructor with vector clone - StructExprTuple(StructExprTuple const& other) : - StructExpr(other), inner_attrs(other.inner_attrs), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - exprs.reserve(other.exprs.size()); - - for (const auto& e : other.exprs) { - exprs.push_back(e->clone_expr()); - } - } - - // overloaded assignment operator with vector clone - StructExprTuple& operator=(StructExprTuple const& other) { - StructExpr::operator=(other); - inner_attrs = other.inner_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - exprs.reserve(other.exprs.size()); - - for (const auto& e : other.exprs) { - exprs.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - StructExprTuple(StructExprTuple&& other) = default; - StructExprTuple& operator=(StructExprTuple&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprTuple* clone_expr_impl() const OVERRIDE { - return new StructExprTuple(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprTuple* clone_expr_without_block_impl() const OVERRIDE { - return new StructExprTuple(*this); - } - }; - - // AST node of a "unit" struct creator (no fields and no braces) - class StructExprUnit : public StructExpr { - Location locus; - - public: - ::std::string as_string() const { - return get_struct_name().as_string(); - // return struct_name.as_string(); - } - - StructExprUnit( - PathInExpression struct_path, ::std::vector<Attribute> outer_attribs, Location locus) : - StructExpr(::std::move(struct_path), ::std::move(outer_attribs)), - locus(locus) {} - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprUnit* clone_expr_impl() const OVERRIDE { - return new StructExprUnit(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual StructExprUnit* clone_expr_without_block_impl() const OVERRIDE { - return new StructExprUnit(*this); - } - }; - - // aka EnumerationVariantExpr - // Base AST node representing creation of an enum variant instance - abstract - class EnumVariantExpr : public ExprWithoutBlock { - PathInExpression enum_variant_path; - - protected: - // Protected constructor for initialising enum_variant_path - EnumVariantExpr( - PathInExpression path_to_enum_variant, ::std::vector<Attribute> outer_attribs) : - ExprWithoutBlock(::std::move(outer_attribs)), - enum_variant_path(::std::move(path_to_enum_variant)) {} - - public: - // TODO: maybe remove and have string version gotten here directly - inline PathInExpression get_enum_variant_path() const { - return enum_variant_path; - } - }; - - // Base AST node for a single enum expression field (in enum instance creation) - abstract - class EnumExprField { - public: - virtual ~EnumExprField() {} - - // Unique pointer custom clone function - ::std::unique_ptr<EnumExprField> clone_enum_expr_field() const { - return ::std::unique_ptr<EnumExprField>(clone_enum_expr_field_impl()); - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // Clone function implementation as pure virtual method - virtual EnumExprField* clone_enum_expr_field_impl() const = 0; - }; - - // Identifier-only variant of EnumExprField AST node - class EnumExprFieldIdentifier : public EnumExprField { - Identifier field_name; - - // TODO: should this store location data? - - public: - EnumExprFieldIdentifier(Identifier field_identifier) : - field_name(::std::move(field_identifier)) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldIdentifier* clone_enum_expr_field_impl() const OVERRIDE { - return new EnumExprFieldIdentifier(*this); - } - }; - - // Base AST node for a single enum expression field with an assigned value - abstract - class EnumExprFieldWithVal : public EnumExprField { - // Expr* value; - ::std::unique_ptr<Expr> value; - - // TODO: should this store location data? - - protected: - EnumExprFieldWithVal(::std::unique_ptr<Expr> field_value) : - value(::std::move(field_value)) {} - - // Copy constructor must clone unique_ptr value - EnumExprFieldWithVal(EnumExprFieldWithVal const& other) : - value(other.value->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - EnumExprFieldWithVal& operator=(EnumExprFieldWithVal const& other) { - value = other.value->clone_expr(); - - return *this; - } - - // move constructors - EnumExprFieldWithVal(EnumExprFieldWithVal&& other) = default; - EnumExprFieldWithVal& operator=(EnumExprFieldWithVal&& other) = default; - }; - - // Identifier and value variant of EnumExprField AST node - class EnumExprFieldIdentifierValue : public EnumExprFieldWithVal { - Identifier field_name; - - // TODO: should this store location data? - - public: - EnumExprFieldIdentifierValue(Identifier field_name, ::std::unique_ptr<Expr> field_value) : - EnumExprFieldWithVal(::std::move(field_value)), field_name(::std::move(field_name)) {} - - // copy constructor, destructor, and assignment operator should not need defining - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldIdentifierValue* clone_enum_expr_field_impl() const OVERRIDE { - return new EnumExprFieldIdentifierValue(*this); - } - }; - - // Tuple index and value variant of EnumExprField AST node - class EnumExprFieldIndexValue : public EnumExprFieldWithVal { - TupleIndex index; - // TODO: implement "with val" as a template with EnumExprField as type param? - - // TODO: should this store location data? - - public: - EnumExprFieldIndexValue(TupleIndex field_index, ::std::unique_ptr<Expr> field_value) : - EnumExprFieldWithVal(::std::move(field_value)), index(field_index) {} - - // copy constructor, destructor, and assignment operator should not need defining - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldIndexValue* clone_enum_expr_field_impl() const OVERRIDE { - return new EnumExprFieldIndexValue(*this); - } - }; - - // Struct-like syntax enum variant instance creation AST node - class EnumExprStruct : public EnumVariantExpr { - //::std::vector<EnumExprField> fields; - ::std::vector< ::std::unique_ptr<EnumExprField> > fields; - - Location locus; - - public: - ::std::string as_string() const; - - /*inline ::std::vector< ::std::unique_ptr<EnumExprField> > get_fields() const { - return fields; - }*/ - - EnumExprStruct(PathInExpression enum_variant_path, - ::std::vector< ::std::unique_ptr<EnumExprField> > variant_fields, - ::std::vector<Attribute> outer_attribs, Location locus) : - EnumVariantExpr(::std::move(enum_variant_path), ::std::move(outer_attribs)), - fields(::std::move(variant_fields)), locus(locus) {} - - // copy constructor with vector clone - EnumExprStruct(EnumExprStruct const& other) : EnumVariantExpr(other), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_enum_expr_field()); - } - } - - // overloaded assignment operator with vector clone - EnumExprStruct& operator=(EnumExprStruct const& other) { - EnumVariantExpr::operator=(other); - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_enum_expr_field()); - } - - return *this; - } - - // move constructors - EnumExprStruct(EnumExprStruct&& other) = default; - EnumExprStruct& operator=(EnumExprStruct&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprStruct* clone_expr_impl() const OVERRIDE { - return new EnumExprStruct(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprStruct* clone_expr_without_block_impl() const OVERRIDE { - return new EnumExprStruct(*this); - } - }; - - // Tuple-like syntax enum variant instance creation AST node - class EnumExprTuple : public EnumVariantExpr { - //::std::vector<Expr> values; - ::std::vector< ::std::unique_ptr<Expr> > values; - - Location locus; - - public: - ::std::string as_string() const; - - /*inline ::std::vector< ::std::unique_ptr<Expr> > get_values() const { - return values; - }*/ - - EnumExprTuple(PathInExpression enum_variant_path, - ::std::vector< ::std::unique_ptr<Expr> > variant_values, - ::std::vector<Attribute> outer_attribs, Location locus) : - EnumVariantExpr(::std::move(enum_variant_path), ::std::move(outer_attribs)), - values(::std::move(variant_values)), locus(locus) {} - - // copy constructor with vector clone - EnumExprTuple(EnumExprTuple const& other) : EnumVariantExpr(other), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - values.reserve(other.values.size()); - - for (const auto& e : other.values) { - values.push_back(e->clone_expr()); - } - } - - // overloaded assignment operator with vector clone - EnumExprTuple& operator=(EnumExprTuple const& other) { - EnumVariantExpr::operator=(other); - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - values.reserve(other.values.size()); - - for (const auto& e : other.values) { - values.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - EnumExprTuple(EnumExprTuple&& other) = default; - EnumExprTuple& operator=(EnumExprTuple&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprTuple* clone_expr_impl() const OVERRIDE { - return new EnumExprTuple(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprTuple* clone_expr_without_block_impl() const OVERRIDE { - return new EnumExprTuple(*this); - } - }; - - // No-field enum variant instance creation AST node - class EnumExprFieldless : public EnumVariantExpr { - Location locus; - - public: - ::std::string as_string() const { - // return enum_variant_path.as_string(); - return get_enum_variant_path().as_string(); - } - - EnumExprFieldless(PathInExpression enum_variant_path, - ::std::vector<Attribute> outer_attribs, Location locus) : - EnumVariantExpr(::std::move(enum_variant_path), ::std::move(outer_attribs)), - locus(locus) {} - - // copy constructor, destructor, and assignment operator should not need defining - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldless* clone_expr_impl() const OVERRIDE { - return new EnumExprFieldless(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual EnumExprFieldless* clone_expr_without_block_impl() const OVERRIDE { - return new EnumExprFieldless(*this); - } - }; - - // Function call expression AST node - class CallExpr : public ExprWithoutBlock { - // Expr* function; - ::std::unique_ptr<Expr> function; - //::std::vector<Expr> params; // inlined form of CallParams - ::std::vector< ::std::unique_ptr<Expr> > params; - - Location locus; - - public: - /*~CallExpr() { - delete function; - }*/ - - ::std::string as_string() const; - - /*inline ::std::vector< ::std::unique_ptr<Expr> > get_params() const { - return params; - }*/ - - CallExpr(::std::unique_ptr<Expr> function_expr, - ::std::vector< ::std::unique_ptr<Expr> > function_params, - ::std::vector<Attribute> outer_attribs, Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - function(::std::move(function_expr)), params(::std::move(function_params)), - locus(locus) {} - - // copy constructor requires clone - CallExpr(CallExpr const& other) : - ExprWithoutBlock(other), function(other.function->clone_expr()), locus(other.locus) - /*, params(other.params),*/ { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - params.reserve(other.params.size()); - - for (const auto& e : other.params) { - params.push_back(e->clone_expr()); - } - } - - // Destructor - define here if required - - // Overload assignment operator to clone - CallExpr& operator=(CallExpr const& other) { - ExprWithoutBlock::operator=(other); - function = other.function->clone_expr(); - locus = other.locus; - // params = other.params; - // outer_attrs = other.outer_attrs; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - params.reserve(other.params.size()); - - for (const auto& e : other.params) { - params.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - CallExpr(CallExpr&& other) = default; - CallExpr& operator=(CallExpr&& other) = default; - - // Returns whether function call has parameters. - inline bool has_params() const { - return !params.empty(); - } - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual CallExpr* clone_expr_impl() const OVERRIDE { - return new CallExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual CallExpr* clone_expr_without_block_impl() const OVERRIDE { - return new CallExpr(*this); - } - }; - - // Method call expression AST node - class MethodCallExpr : public ExprWithoutBlock { - // Expr* receiver; - ::std::unique_ptr<Expr> receiver; - PathExprSegment method_name; - //::std::vector<Expr> params; // inlined form of CallParams - ::std::vector< ::std::unique_ptr<Expr> > params; - - Location locus; - - public: - /*~MethodCallExpr() { - delete receiver; - }*/ - - ::std::string as_string() const; - - /*inline ::std::vector< ::std::unique_ptr<Expr> > get_params() const { - return params; - }*/ - - MethodCallExpr(::std::unique_ptr<Expr> call_receiver, PathExprSegment method_path, - ::std::vector< ::std::unique_ptr<Expr> > method_params, - ::std::vector<Attribute> outer_attribs, Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - receiver(::std::move(call_receiver)), method_name(::std::move(method_path)), - params(::std::move(method_params)), locus(locus) {} - - // copy constructor required due to cloning - MethodCallExpr(MethodCallExpr const& other) : - ExprWithoutBlock(other), receiver(other.receiver->clone_expr()), - method_name(other.method_name), locus(other.locus) - /*, params(other.params),*/ { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - params.reserve(other.params.size()); - - for (const auto& e : other.params) { - params.push_back(e->clone_expr()); - } - } - - // Destructor - define here if required - - // Overload assignment operator to clone receiver object - MethodCallExpr& operator=(MethodCallExpr const& other) { - ExprWithoutBlock::operator=(other); - receiver = other.receiver->clone_expr(); - method_name = other.method_name; - locus = other.locus; - // params = other.params; - // outer_attrs = other.outer_attrs; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - params.reserve(other.params.size()); - - for (const auto& e : other.params) { - params.push_back(e->clone_expr()); - } - - return *this; - } - - // move constructors - MethodCallExpr(MethodCallExpr&& other) = default; - MethodCallExpr& operator=(MethodCallExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MethodCallExpr* clone_expr_impl() const OVERRIDE { - return new MethodCallExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MethodCallExpr* clone_expr_without_block_impl() const OVERRIDE { - return new MethodCallExpr(*this); - } - }; - - // aka FieldExpression - // Struct or union field access expression AST node - class FieldAccessExpr : public ExprWithoutBlock { - // Expr* receiver; - ::std::unique_ptr<Expr> receiver; - Identifier field; - - Location locus; - - public: - /*~FieldAccessExpr() { - delete receiver; - }*/ - - ::std::string as_string() const; - - FieldAccessExpr(::std::unique_ptr<Expr> field_access_receiver, Identifier field_name, - ::std::vector<Attribute> outer_attribs, Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - receiver(::std::move(field_access_receiver)), field(::std::move(field_name)), - locus(locus) {} - - // Copy constructor required due to unique_ptr cloning - FieldAccessExpr(FieldAccessExpr const& other) : - ExprWithoutBlock(other), receiver(other.receiver->clone_expr()), field(other.field), - locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr - FieldAccessExpr& operator=(FieldAccessExpr const& other) { - ExprWithoutBlock::operator=(other); - receiver = other.receiver->clone_expr(); - field = other.field; - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - FieldAccessExpr(FieldAccessExpr&& other) = default; - FieldAccessExpr& operator=(FieldAccessExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual FieldAccessExpr* clone_expr_impl() const OVERRIDE { - return new FieldAccessExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual FieldAccessExpr* clone_expr_without_block_impl() const OVERRIDE { - return new FieldAccessExpr(*this); - } - }; - - // Closure parameter data structure - struct ClosureParam { - private: - // Pattern pattern; - ::std::unique_ptr<Pattern> pattern; - - // bool has_type_given; - // Type type; - ::std::unique_ptr<Type> type; - - // TODO: should this store location data? - - public: - // Returns whether the type of the parameter has been given. - inline bool has_type_given() const { - return type != NULL; - } - - // Constructor for closure parameter - ClosureParam( - ::std::unique_ptr<Pattern> param_pattern, ::std::unique_ptr<Type> param_type = NULL) : - pattern(::std::move(param_pattern)), - type(::std::move(param_type)) {} - - // Copy constructor required due to cloning as a result of unique_ptrs - ClosureParam(ClosureParam const& other) : pattern(other.pattern->clone_pattern()) { - // guard to protect from null pointer dereference - if (other.type != NULL) { - type = other.type->clone_type(); - } - } - - ~ClosureParam() = default; - - // Assignment operator must be overloaded to clone as well - ClosureParam& operator=(ClosureParam const& other) { - pattern = other.pattern->clone_pattern(); - type = other.type->clone_type(); - - return *this; - } - - // move constructors - ClosureParam(ClosureParam&& other) = default; - ClosureParam& operator=(ClosureParam&& other) = default; - - // Returns whether closure parameter is in an error state. - inline bool is_error() const { - return pattern == NULL; - } - - // Creates an error state closure parameter. - static ClosureParam create_error() { - return ClosureParam(NULL); - } - - ::std::string as_string() const; - }; - - // Base closure definition expression AST node - abstract - class ClosureExpr : public ExprWithoutBlock { - bool has_move; - ::std::vector<ClosureParam> params; // may be empty - // also note a double pipe "||" can be used for empty params - does not need a space - - Location locus; - - protected: - ClosureExpr(::std::vector<ClosureParam> closure_params, bool has_move, - ::std::vector<Attribute> outer_attribs, Location locus) : - ExprWithoutBlock(::std::move(outer_attribs)), - has_move(has_move), params(::std::move(closure_params)), locus(locus) {} - - // Copy constructor, destructor, and assignment operator override should not be needed - public: - virtual ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - }; - - // Represents a non-type-specified closure expression AST node - class ClosureExprInner : public ClosureExpr { - // Expr* closure_inner; - ::std::unique_ptr<Expr> closure_inner; - - public: - /*~ClosureExprInner() { - delete closure_inner; - }*/ - - ::std::string as_string() const; - - // Constructor for a ClosureExprInner - ClosureExprInner(::std::unique_ptr<Expr> closure_inner_expr, - ::std::vector<ClosureParam> closure_params, Location locus, bool is_move = false, - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - ClosureExpr(::std::move(closure_params), is_move, ::std::move(outer_attribs), locus), - closure_inner(::std::move(closure_inner_expr)) {} - - // Copy constructor must be defined to allow copying via cloning of unique_ptr - ClosureExprInner(ClosureExprInner const& other) : - ClosureExpr(other), closure_inner(other.closure_inner->clone_expr()) {} - // TODO: ensure that this actually constructs properly - - // Destructor - define here if required - - // Overload assignment operator to clone closure_inner - ClosureExprInner& operator=(ClosureExprInner const& other) { - ClosureExpr::operator=(other); - closure_inner = other.closure_inner->clone_expr(); - // params = other.params; - // has_move = other.has_move; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ClosureExprInner(ClosureExprInner&& other) = default; - ClosureExprInner& operator=(ClosureExprInner&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ClosureExprInner* clone_expr_impl() const OVERRIDE { - return new ClosureExprInner(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ClosureExprInner* clone_expr_without_block_impl() const OVERRIDE { - return new ClosureExprInner(*this); - } - }; - - // Forward decl BlockExpr for ClosureExprInnerTyped - // class BlockExpr; - - // A block AST node - class BlockExpr : public ExprWithBlock { - ::std::vector<Attribute> inner_attrs; - - /*bool has_statements; - Statements statements;*/ - - // bool has_statements; - ::std::vector< ::std::unique_ptr<Stmt> > statements; - // bool has_expr; - ::std::unique_ptr<ExprWithoutBlock> expr; // inlined from Statements - - Location locus; - - public: - ::std::string as_string() const; - - // Returns whether the block contains statements. - inline bool has_statements() const { - return !statements.empty(); - } - - // Returns whether the block contains an expression - inline bool has_expr() const { - return expr != NULL; - } - - BlockExpr(::std::vector< ::std::unique_ptr<Stmt> > block_statements, - ::std::unique_ptr<ExprWithoutBlock> block_expr, ::std::vector<Attribute> inner_attribs, - ::std::vector<Attribute> outer_attribs, Location locus) : - ExprWithBlock(::std::move(outer_attribs)), - inner_attrs(::std::move(inner_attribs)), statements(::std::move(block_statements)), - expr(::std::move(block_expr)), locus(locus) {} - - // Copy constructor with clone - BlockExpr(BlockExpr const& other) : - ExprWithBlock(other), /*statements(other.statements),*/ - inner_attrs(other.inner_attrs), locus(other.locus) { - // guard to protect from null pointer dereference - if (other.expr != NULL) { - expr = other.expr->clone_expr_without_block(); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - statements.reserve(other.statements.size()); - - for (const auto& e : other.statements) { - statements.push_back(e->clone_stmt()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone pointer - BlockExpr& operator=(BlockExpr const& other) { - ExprWithBlock::operator=(other); - // statements = other.statements; - expr = other.expr->clone_expr_without_block(); - inner_attrs = other.inner_attrs; - locus = other.locus; - // outer_attrs = other.outer_attrs; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - statements.reserve(other.statements.size()); - - for (const auto& e : other.statements) { - statements.push_back(e->clone_stmt()); - } - - return *this; - } - - // move constructors - BlockExpr(BlockExpr&& other) = default; - BlockExpr& operator=(BlockExpr&& other) = default; - - // Unique pointer custom clone function - ::std::unique_ptr<BlockExpr> clone_block_expr() const { - return ::std::unique_ptr<BlockExpr>(clone_block_expr_impl()); - } - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual BlockExpr* clone_expr_impl() const OVERRIDE { - return new BlockExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual BlockExpr* clone_expr_with_block_impl() const OVERRIDE { - return new BlockExpr(*this); - } - - /* This is the base method as not an abstract class - not virtual but could be in future - * if required. */ - /*virtual*/ BlockExpr* clone_block_expr_impl() const { - return new BlockExpr(*this); - } - }; - - // Represents a type-specified closure expression AST node - class ClosureExprInnerTyped : public ClosureExpr { - // Type return_type; - ::std::unique_ptr<Type> return_type; - // BlockExpr* expr; - ::std::unique_ptr<BlockExpr> expr; // only used because may be polymorphic in future - - public: - /*~ClosureExprInnerTyped() { - delete expr; - }*/ - - ::std::string as_string() const; - - // Constructor potentially with a move - ClosureExprInnerTyped(::std::unique_ptr<Type> closure_return_type, - ::std::unique_ptr<BlockExpr> closure_expr, ::std::vector<ClosureParam> closure_params, - Location locus, bool is_move = false, - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - ClosureExpr(::std::move(closure_params), is_move, ::std::move(outer_attribs), locus), - return_type(::std::move(closure_return_type)), expr(::std::move(closure_expr)) {} - - // Copy constructor requires cloning - ClosureExprInnerTyped(ClosureExprInnerTyped const& other) : - ClosureExpr(other), return_type(other.return_type->clone_type()), - expr(other.expr->clone_block_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptrs - ClosureExprInnerTyped& operator=(ClosureExprInnerTyped const& other) { - ClosureExpr::operator=(other); - return_type = other.return_type->clone_type(); - expr = other.expr->clone_block_expr(); - // params = other.params; - // has_move = other.has_move; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ClosureExprInnerTyped(ClosureExprInnerTyped&& other) = default; - ClosureExprInnerTyped& operator=(ClosureExprInnerTyped&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ClosureExprInnerTyped* clone_expr_impl() const OVERRIDE { - return new ClosureExprInnerTyped(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ClosureExprInnerTyped* clone_expr_without_block_impl() const OVERRIDE { - return new ClosureExprInnerTyped(*this); - } - }; - - // AST node representing continue expression within loops - class ContinueExpr : public ExprWithoutBlock { - // bool has_label; - Lifetime label; - - Location locus; - - public: - ::std::string as_string() const; - - // Returns true if the continue expr has a label. - inline bool has_label() const { - return !label.is_error(); - } - - // Constructor for a ContinueExpr with a label. - ContinueExpr(Location locus, Lifetime label = Lifetime::error(), - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - ExprWithoutBlock(::std::move(outer_attribs)), - label(::std::move(label)), locus(locus) {} - - // copy constructor, destructor, and assignment operator should not need defining - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ContinueExpr* clone_expr_impl() const OVERRIDE { - return new ContinueExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ContinueExpr* clone_expr_without_block_impl() const OVERRIDE { - return new ContinueExpr(*this); - } - }; - // TODO: merge "break" and "continue"? Or even merge in "return"? - - // AST node representing break expression within loops - class BreakExpr : public ExprWithoutBlock { - // bool has_label; - Lifetime label; - - // bool has_break_expr; - // Expr* break_expr; // may be uninitialised - ::std::unique_ptr<Expr> break_expr; - - Location locus; - - public: - /*~BreakExpr() { - if (has_break_expr) { - delete break_expr; - } - }*/ - - ::std::string as_string() const; - - // Returns whether the break expression has a label or not. - inline bool has_label() const { - return !label.is_error(); - } - - // Returns whether the break expression has an expression used in the break or not. - inline bool has_break_expr() const { - return break_expr != NULL; - } - - // Constructor for a break expression - BreakExpr(Location locus, Lifetime break_label = Lifetime::error(), - ::std::unique_ptr<Expr> expr_in_break = NULL, - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - ExprWithoutBlock(::std::move(outer_attribs)), - label(::std::move(break_label)), break_expr(::std::move(expr_in_break)), locus(locus) {} - - // Copy constructor defined to use clone for unique pointer - BreakExpr(BreakExpr const& other) : - ExprWithoutBlock(other), label(other.label), locus(other.locus) { - // guard to protect from null pointer dereference - if (other.break_expr != NULL) { - break_expr = other.break_expr->clone_expr(); - } - } - - // Destructor - define here if required - - // Overload assignment operator to clone unique pointer - BreakExpr& operator=(BreakExpr const& other) { - ExprWithoutBlock::operator=(other); - label = other.label; - break_expr = other.break_expr->clone_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - BreakExpr(BreakExpr&& other) = default; - BreakExpr& operator=(BreakExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual BreakExpr* clone_expr_impl() const OVERRIDE { - return new BreakExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual BreakExpr* clone_expr_without_block_impl() const OVERRIDE { - return new BreakExpr(*this); - } - }; - - // Base range expression AST node object - abstract - class RangeExpr : public ExprWithoutBlock { - Location locus; - - protected: - // outer attributes not allowed before range expressions - RangeExpr(Location locus) : ExprWithoutBlock(::std::vector<Attribute>()), locus(locus) {} - - public: - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - }; - - // Range from (inclusive) and to (exclusive) expression AST node object - // aka RangeExpr; constructs a std::ops::Range object - class RangeFromToExpr : public RangeExpr { - /*Expr* from; - Expr* to;*/ - ::std::unique_ptr<Expr> from; - ::std::unique_ptr<Expr> to; - - public: - /*~RangeFromToExpr() { - delete from; - delete to; - }*/ - - ::std::string as_string() const; - - RangeFromToExpr( - ::std::unique_ptr<Expr> range_from, ::std::unique_ptr<Expr> range_to, Location locus) : - RangeExpr(locus), - from(::std::move(range_from)), to(::std::move(range_to)) {} - - // Copy constructor with cloning - RangeFromToExpr(RangeFromToExpr const& other) : - RangeExpr(other), from(other.from->clone_expr()), to(other.to->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique pointers - RangeFromToExpr& operator=(RangeFromToExpr const& other) { - RangeExpr::operator=(other); - from = other.from->clone_expr(); - to = other.to->clone_expr(); - - return *this; - } - - // move constructors - RangeFromToExpr(RangeFromToExpr&& other) = default; - RangeFromToExpr& operator=(RangeFromToExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromToExpr* clone_expr_impl() const OVERRIDE { - return new RangeFromToExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromToExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeFromToExpr(*this); - } - }; - - // Range from (inclusive) expression AST node object - // constructs a std::ops::RangeFrom object - class RangeFromExpr : public RangeExpr { - // Expr* from; - ::std::unique_ptr<Expr> from; - - public: - /*~RangeFromExpr() { - delete from; - }*/ - - ::std::string as_string() const; - - RangeFromExpr(::std::unique_ptr<Expr> range_from, Location locus) : - RangeExpr(locus), from(::std::move(range_from)) {} - - // Copy constructor with clone - RangeFromExpr(RangeFromExpr const& other) : - RangeExpr(other), from(other.from->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr - RangeFromExpr& operator=(RangeFromExpr const& other) { - RangeExpr::operator=(other); - from = other.from->clone_expr(); - - return *this; - } - - // move constructors - RangeFromExpr(RangeFromExpr&& other) = default; - RangeFromExpr& operator=(RangeFromExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromExpr* clone_expr_impl() const OVERRIDE { - return new RangeFromExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeFromExpr(*this); - } - }; - - // Range to (exclusive) expression AST node object - // constructs a std::ops::RangeTo object - class RangeToExpr : public RangeExpr { - // Expr* to; - ::std::unique_ptr<Expr> to; - - public: - /*~RangeToExpr() { - delete to; - }*/ - - ::std::string as_string() const; - - // outer attributes not allowed - RangeToExpr(::std::unique_ptr<Expr> range_to, Location locus) : - RangeExpr(locus), to(::std::move(range_to)) {} - - // Copy constructor with clone - RangeToExpr(RangeToExpr const& other) : RangeExpr(other), to(other.to->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone unique_ptr - RangeToExpr& operator=(RangeToExpr const& other) { - RangeExpr::operator=(other); - to = other.to->clone_expr(); - - return *this; - } - - // move constructors - RangeToExpr(RangeToExpr&& other) = default; - RangeToExpr& operator=(RangeToExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeToExpr* clone_expr_impl() const OVERRIDE { - return new RangeToExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeToExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeToExpr(*this); - } - }; - - // Full range expression AST node object - // constructs a std::ops::RangeFull object - class RangeFullExpr : public RangeExpr { - public: - ::std::string as_string() const; - - RangeFullExpr(Location locus) : RangeExpr(locus) {} - // outer attributes not allowed - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFullExpr* clone_expr_impl() const OVERRIDE { - return new RangeFullExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFullExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeFullExpr(*this); - } - }; - - // Range from (inclusive) and to (inclusive) expression AST node object - // aka RangeInclusiveExpr; constructs a std::ops::RangeInclusive object - class RangeFromToInclExpr : public RangeExpr { - /*Expr* from; - Expr* to;*/ - ::std::unique_ptr<Expr> from; - ::std::unique_ptr<Expr> to; - - public: - /*~RangeFromToInclExpr() { - delete from; - delete to; - }*/ - - ::std::string as_string() const; - - RangeFromToInclExpr( - ::std::unique_ptr<Expr> range_from, ::std::unique_ptr<Expr> range_to, Location locus) : - RangeExpr(locus), - from(::std::move(range_from)), to(::std::move(range_to)) {} - // outer attributes not allowed - - // Copy constructor with clone - RangeFromToInclExpr(RangeFromToInclExpr const& other) : - RangeExpr(other), from(other.from->clone_expr()), to(other.to->clone_expr()) {} - - // Destructor - define here if required - - // Overload assignment operator to use clone - RangeFromToInclExpr& operator=(RangeFromToInclExpr const& other) { - RangeExpr::operator=(other); - from = other.from->clone_expr(); - to = other.to->clone_expr(); - - return *this; - } - - // move constructors - RangeFromToInclExpr(RangeFromToInclExpr&& other) = default; - RangeFromToInclExpr& operator=(RangeFromToInclExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromToInclExpr* clone_expr_impl() const OVERRIDE { - return new RangeFromToInclExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeFromToInclExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeFromToInclExpr(*this); - } - }; - - // Range to (inclusive) expression AST node object - // aka RangeToInclusiveExpr; constructs a std::ops::RangeToInclusive object - class RangeToInclExpr : public RangeExpr { - // Expr* to; - ::std::unique_ptr<Expr> to; - - public: - /*~RangeToInclExpr() { - delete to; - }*/ - - ::std::string as_string() const; - - RangeToInclExpr(::std::unique_ptr<Expr> range_to, Location locus) : - RangeExpr(locus), to(::std::move(range_to)) {} - // outer attributes not allowed - - // Copy constructor with clone - RangeToInclExpr(RangeToInclExpr const& other) : - RangeExpr(other), to(other.to->clone_expr()) {} - - // Define destructor here if required - - // Overload assignment operator to clone pointer - RangeToInclExpr& operator=(RangeToInclExpr const& other) { - RangeExpr::operator=(other); - to = other.to->clone_expr(); - - return *this; - } - - // move constructors - RangeToInclExpr(RangeToInclExpr&& other) = default; - RangeToInclExpr& operator=(RangeToInclExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangeToInclExpr* clone_expr_impl() const OVERRIDE { - return new RangeToInclExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RangeToInclExpr* clone_expr_without_block_impl() const OVERRIDE { - return new RangeToInclExpr(*this); - } - }; - - // Return expression AST node representation - class ReturnExpr : public ExprWithoutBlock { - // bool has_return_expr; - // Expr* return_expr; - ::std::unique_ptr<Expr> return_expr; - - Location locus; - - public: - /*~ReturnExpr() { - if (has_return_expr) { - delete return_expr; - } - }*/ - - ::std::string as_string() const; - - // Returns whether the object has an expression returned (i.e. not void return type). - inline bool has_return_expr() const { - return return_expr != NULL; - } - - // Constructor for ReturnExpr. - ReturnExpr(Location locus, ::std::unique_ptr<Expr> returned_expr = NULL, - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - ExprWithoutBlock(::std::move(outer_attribs)), - return_expr(::std::move(returned_expr)), locus(locus) {} - - // Copy constructor with clone - ReturnExpr(ReturnExpr const& other) : ExprWithoutBlock(other), locus(other.locus) { - // guard to protect from null pointer dereference - if (other.return_expr != NULL) { - return_expr = other.return_expr->clone_expr(); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone return_expr pointer - ReturnExpr& operator=(ReturnExpr const& other) { - ExprWithoutBlock::operator=(other); - return_expr = other.return_expr->clone_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - ReturnExpr(ReturnExpr&& other) = default; - ReturnExpr& operator=(ReturnExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ReturnExpr* clone_expr_impl() const OVERRIDE { - return new ReturnExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ReturnExpr* clone_expr_without_block_impl() const OVERRIDE { - return new ReturnExpr(*this); - } - }; - - // Forward decl - defined in rust-macro.h - class MacroInvocation; - /*class MacroInvocation : public ExprWithoutBlock { - public: - ::std::string as_string() const; - };*/ - - // An unsafe block AST node - class UnsafeBlockExpr : public ExprWithBlock { - // Or just have it extend BlockExpr - // BlockExpr* expr; - ::std::unique_ptr<BlockExpr> expr; - - Location locus; - - public: - /*~UnsafeBlockExpr() { - delete expr; - }*/ - - ::std::string as_string() const; - - UnsafeBlockExpr(::std::unique_ptr<BlockExpr> block_expr, - ::std::vector<Attribute> outer_attribs, Location locus) : - ExprWithBlock(::std::move(outer_attribs)), - expr(::std::move(block_expr)), locus(locus) {} - - // Copy constructor with clone - UnsafeBlockExpr(UnsafeBlockExpr const& other) : - ExprWithBlock(other), expr(other.expr->clone_block_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - UnsafeBlockExpr& operator=(UnsafeBlockExpr const& other) { - ExprWithBlock::operator=(other); - expr = other.expr->clone_block_expr(); - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - UnsafeBlockExpr(UnsafeBlockExpr&& other) = default; - UnsafeBlockExpr& operator=(UnsafeBlockExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual UnsafeBlockExpr* clone_expr_impl() const OVERRIDE { - return new UnsafeBlockExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual UnsafeBlockExpr* clone_expr_with_block_impl() const OVERRIDE { - return new UnsafeBlockExpr(*this); - } - }; - - // Loop label expression AST node used with break and continue expressions - // TODO: inline? - class LoopLabel /*: public Node*/ { - Lifetime label; // or type LIFETIME_OR_LABEL - - Location locus; - - public: - ::std::string as_string() const; - - LoopLabel(Lifetime loop_label, Location locus = Location()) : - label(::std::move(loop_label)), locus(locus) {} - - // Returns whether the LoopLabel is in an error state. - inline bool is_error() const { - return label.is_error(); - } - - // Creates an error state LoopLabel. - static LoopLabel error() { - return LoopLabel(Lifetime::error()); - } - - Location get_locus() const { - return locus; - } - }; - - // Base loop expression AST node - aka LoopExpr - class BaseLoopExpr : public ExprWithBlock { - protected: - // protected to allow subclasses better use of them - // bool has_loop_label; - LoopLabel loop_label; - - // BlockExpr* loop_block; - ::std::unique_ptr<BlockExpr> loop_block; - - private: - Location locus; - - protected: - // Constructor for BaseLoopExpr - BaseLoopExpr(::std::unique_ptr<BlockExpr> loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error(), - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - ExprWithBlock(::std::move(outer_attribs)), - loop_label(::std::move(loop_label)), loop_block(::std::move(loop_block)), locus(locus) { - } - - // Copy constructor for BaseLoopExpr with clone - BaseLoopExpr(BaseLoopExpr const& other) : - ExprWithBlock(other), loop_label(other.loop_label), - loop_block(other.loop_block->clone_block_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - BaseLoopExpr& operator=(BaseLoopExpr const& other) { - ExprWithBlock::operator=(other); - loop_block = other.loop_block->clone_block_expr(); - loop_label = other.loop_label; - locus = other.locus; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - BaseLoopExpr(BaseLoopExpr&& other) = default; - BaseLoopExpr& operator=(BaseLoopExpr&& other) = default; - - public: - /*~BaseLoopExpr() { - delete loop_block; - }*/ - - inline bool has_loop_label() const { - return !loop_label.is_error(); - } - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - }; - - // 'Loop' expression (i.e. the infinite loop) AST node - class LoopExpr : public BaseLoopExpr { - public: - ::std::string as_string() const; - - // Constructor for LoopExpr - LoopExpr(::std::unique_ptr<BlockExpr> loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error(), - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - BaseLoopExpr(::std::move(loop_block), locus, ::std::move(loop_label), - ::std::move(outer_attribs)) {} - - // copy constructor, destructor, and assignment operator should not need modification - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LoopExpr* clone_expr_impl() const OVERRIDE { - return new LoopExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual LoopExpr* clone_expr_with_block_impl() const OVERRIDE { - return new LoopExpr(*this); - } - }; - - // While loop expression AST node (predicate loop) - class WhileLoopExpr : public BaseLoopExpr { - // Expr* condition; - ::std::unique_ptr<Expr> condition; - - public: - /*~WhileLoopExpr() { - delete condition; - }*/ - - ::std::string as_string() const; - - // Constructor for while loop with loop label - WhileLoopExpr(::std::unique_ptr<Expr> loop_condition, - ::std::unique_ptr<BlockExpr> loop_block, Location locus, - LoopLabel loop_label = LoopLabel::error(), - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - BaseLoopExpr( - ::std::move(loop_block), locus, ::std::move(loop_label), ::std::move(outer_attribs)), - condition(::std::move(loop_condition)) {} - - // Copy constructor with clone - WhileLoopExpr(WhileLoopExpr const& other) : - BaseLoopExpr(other), condition(other.condition->clone_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - WhileLoopExpr& operator=(WhileLoopExpr const& other) { - BaseLoopExpr::operator=(other); - condition = other.condition->clone_expr(); - // loop_block = other.loop_block->clone_block_expr(); - // loop_label = other.loop_label; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - WhileLoopExpr(WhileLoopExpr&& other) = default; - WhileLoopExpr& operator=(WhileLoopExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual WhileLoopExpr* clone_expr_impl() const OVERRIDE { - return new WhileLoopExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual WhileLoopExpr* clone_expr_with_block_impl() const OVERRIDE { - return new WhileLoopExpr(*this); - } - }; - - // Forward decl MatchArmPatterns - // struct MatchArmPatterns; - - // While let loop expression AST node (predicate pattern loop) - class WhileLetLoopExpr : public BaseLoopExpr { - // MatchArmPatterns patterns; - ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns; // inlined - // Expr* condition; - ::std::unique_ptr<Expr> condition; - - public: - /*~WhileLetLoopExpr() { - delete condition; - }*/ - - ::std::string as_string() const; - - // Constructor with a loop label - WhileLetLoopExpr(::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, - ::std::unique_ptr<Expr> condition, ::std::unique_ptr<BlockExpr> loop_block, - Location locus, LoopLabel loop_label = LoopLabel::error(), - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - BaseLoopExpr( - ::std::move(loop_block), locus, ::std::move(loop_label), ::std::move(outer_attribs)), - match_arm_patterns(::std::move(match_arm_patterns)), condition(::std::move(condition)) { - } - - // Copy constructor with clone - WhileLetLoopExpr(WhileLetLoopExpr const& other) : - BaseLoopExpr(other), /*match_arm_patterns(other.match_arm_patterns),*/ condition( - other.condition->clone_expr()) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone pointers - WhileLetLoopExpr& operator=(WhileLetLoopExpr const& other) { - BaseLoopExpr::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - condition = other.condition->clone_expr(); - // loop_block = other.loop_block->clone_block_expr(); - // loop_label = other.loop_label; - // outer_attrs = other.outer_attrs; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - WhileLetLoopExpr(WhileLetLoopExpr&& other) = default; - WhileLetLoopExpr& operator=(WhileLetLoopExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual WhileLetLoopExpr* clone_expr_impl() const OVERRIDE { - return new WhileLetLoopExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual WhileLetLoopExpr* clone_expr_with_block_impl() const OVERRIDE { - return new WhileLetLoopExpr(*this); - } - }; - - // For loop expression AST node (iterator loop) - class ForLoopExpr : public BaseLoopExpr { - // Pattern pattern; - ::std::unique_ptr<Pattern> pattern; - // Expr* iterator_expr; - ::std::unique_ptr<Expr> iterator_expr; - - public: - /*~ForLoopExpr() { - delete iterator_expr; - }*/ - - ::std::string as_string() const; - - // Constructor with loop label - ForLoopExpr(::std::unique_ptr<Pattern> loop_pattern, - ::std::unique_ptr<Expr> iterator_expr, ::std::unique_ptr<BlockExpr> loop_body, - Location locus, LoopLabel loop_label = LoopLabel::error(), - ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute>()) : - BaseLoopExpr( - ::std::move(loop_body), locus, ::std::move(loop_label), ::std::move(outer_attribs)), - pattern(::std::move(loop_pattern)), iterator_expr(::std::move(iterator_expr)) {} - - // Copy constructor with clone - ForLoopExpr(ForLoopExpr const& other) : - BaseLoopExpr(other), pattern(other.pattern->clone_pattern()), - iterator_expr(other.iterator_expr->clone_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - ForLoopExpr& operator=(ForLoopExpr const& other) { - BaseLoopExpr::operator=(other); - pattern = other.pattern->clone_pattern(); - iterator_expr = other.iterator_expr->clone_expr(); - /*loop_block = other.loop_block->clone_block_expr(); - loop_label = other.loop_label; - outer_attrs = other.outer_attrs;*/ - - return *this; - } - - // move constructors - ForLoopExpr(ForLoopExpr&& other) = default; - ForLoopExpr& operator=(ForLoopExpr&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ForLoopExpr* clone_expr_impl() const OVERRIDE { - return new ForLoopExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ForLoopExpr* clone_expr_with_block_impl() const OVERRIDE { - return new ForLoopExpr(*this); - } - }; - - // forward decl for IfExpr - class IfLetExpr; - - // Base if expression with no "else" or "if let" AST node - class IfExpr : public ExprWithBlock { - /*Expr* condition; - BlockExpr* if_block;*/ - ::std::unique_ptr<Expr> condition; - ::std::unique_ptr<BlockExpr> if_block; - /*union { - BlockExpr else_block; - IfExpr* if_expr; - IfLetExpr if_let_expr; - } consequent_block;*/ - - Location locus; - - public: - /*virtual ~IfExpr() { - delete condition; - delete if_block; - }*/ - - ::std::string as_string() const; - - IfExpr(::std::unique_ptr<Expr> condition, ::std::unique_ptr<BlockExpr> if_block, - Location locus) : - ExprWithBlock(::std::vector<Attribute>()), - condition(::std::move(condition)), if_block(::std::move(if_block)), locus(locus) {} - // outer attributes are never allowed on IfExprs - - // Copy constructor with clone - IfExpr(IfExpr const& other) : - ExprWithBlock(other), condition(other.condition->clone_expr()), - if_block(other.if_block->clone_block_expr()), locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone expressions - IfExpr& operator=(IfExpr const& other) { - ExprWithBlock::operator=(other); - condition = other.condition->clone_expr(); - if_block = other.if_block->clone_block_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - IfExpr(IfExpr&& other) = default; - IfExpr& operator=(IfExpr&& other) = default; - - // Unique pointer custom clone function - ::std::unique_ptr<IfExpr> clone_if_expr() const { - return ::std::unique_ptr<IfExpr>(clone_if_expr_impl()); - } - - /* Note that multiple "else if"s are handled via nested ASTs rather than a vector of - * else ifs - i.e. not like a switch statement. TODO - is this a better approach? or - * does it not parse correctly and have downsides? */ - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfExpr* clone_expr_impl() const OVERRIDE { - return new IfExpr(*this); - } - - // Base clone function but still concrete as concrete base class - virtual IfExpr* clone_if_expr_impl() const { - return new IfExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExpr* clone_expr_with_block_impl() const OVERRIDE { - return new IfExpr(*this); - } - }; - - // If expression with an ending "else" expression AST node (trailing) - class IfExprConseqElse : public IfExpr { - // BlockExpr* else_block; - ::std::unique_ptr<BlockExpr> else_block; - - public: - /*~IfExprConseqElse() { - delete else_block; - }*/ - - ::std::string as_string() const; - - IfExprConseqElse(::std::unique_ptr<Expr> condition, ::std::unique_ptr<BlockExpr> if_block, - ::std::unique_ptr<BlockExpr> else_block, Location locus) : - IfExpr(::std::move(condition), ::std::move(if_block), locus), - else_block(::std::move(else_block)) {} - // again, outer attributes not allowed - - // Copy constructor with clone - IfExprConseqElse(IfExprConseqElse const& other) : - IfExpr(other), else_block(other.else_block->clone_block_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator with cloning - IfExprConseqElse& operator=(IfExprConseqElse const& other) { - IfExpr::operator=(other); - // condition = other.condition->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - else_block = other.else_block->clone_block_expr(); - - return *this; - } - - // move constructors - IfExprConseqElse(IfExprConseqElse&& other) = default; - IfExprConseqElse& operator=(IfExprConseqElse&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqElse* clone_expr_impl() const OVERRIDE { - return new IfExprConseqElse(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqElse* clone_expr_with_block_impl() const OVERRIDE { - return new IfExprConseqElse(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqElse* clone_if_expr_impl() const OVERRIDE { - return new IfExprConseqElse(*this); - } - }; - - // If expression with an ending "else if" expression AST node - class IfExprConseqIf : public IfExpr { - // IfExpr* if_expr; - ::std::unique_ptr<IfExpr> if_expr; - - public: - /*~IfExprConseqIf() { - delete if_expr; - }*/ - - ::std::string as_string() const; - - IfExprConseqIf(::std::unique_ptr<Expr> condition, ::std::unique_ptr<BlockExpr> if_block, - ::std::unique_ptr<IfExpr> conseq_if_expr, Location locus) : - IfExpr(::std::move(condition), ::std::move(if_block), locus), - if_expr(::std::move(conseq_if_expr)) {} - // outer attributes not allowed - - // Copy constructor with clone - IfExprConseqIf(IfExprConseqIf const& other) : - IfExpr(other), if_expr(other.if_expr->clone_if_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to use clone - IfExprConseqIf& operator=(IfExprConseqIf const& other) { - IfExpr::operator=(other); - // condition = other.condition->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - if_expr = other.if_expr->clone_if_expr(); - - return *this; - } - - // move constructors - IfExprConseqIf(IfExprConseqIf&& other) = default; - IfExprConseqIf& operator=(IfExprConseqIf&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIf* clone_expr_impl() const OVERRIDE { - return new IfExprConseqIf(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIf* clone_expr_with_block_impl() const OVERRIDE { - return new IfExprConseqIf(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIf* clone_if_expr_impl() const OVERRIDE { - return new IfExprConseqIf(*this); - } - }; - - // Basic "if let" expression AST node with no else - class IfLetExpr : public ExprWithBlock { - // MatchArmPatterns patterns; - ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns; // inlined - /*Expr* value; - BlockExpr* if_block;*/ - ::std::unique_ptr<Expr> value; - ::std::unique_ptr<BlockExpr> if_block; - /*union { - BlockExpr else_block; - IfExpr if_expr; - IfLetExpr* if_let_expr; - } consequent_block;*/ - - Location locus; - - public: - ::std::string as_string() const; - - IfLetExpr(::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, - ::std::unique_ptr<Expr> value, ::std::unique_ptr<BlockExpr> if_block, Location locus) : - ExprWithBlock(::std::vector<Attribute>()), - match_arm_patterns(::std::move(match_arm_patterns)), value(::std::move(value)), - if_block(::std::move(if_block)), locus(locus) {} - // outer attributes not allowed on if let exprs either - - // copy constructor with clone - IfLetExpr(IfLetExpr const& other) : - ExprWithBlock(other), - /*match_arm_patterns(other.match_arm_patterns),*/ value(other.value->clone_expr()), - if_block(other.if_block->clone_block_expr()), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - } - - // destructor - define here if required - - // overload assignment operator to clone - IfLetExpr& operator=(IfLetExpr const& other) { - ExprWithBlock::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - value = other.value->clone_expr(); - if_block = other.if_block->clone_block_expr(); - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - IfLetExpr(IfLetExpr&& other) = default; - IfLetExpr& operator=(IfLetExpr&& other) = default; - - // Unique pointer custom clone function - ::std::unique_ptr<IfLetExpr> clone_if_let_expr() const { - return ::std::unique_ptr<IfLetExpr>(clone_if_let_expr_impl()); - } - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExpr* clone_expr_impl() const OVERRIDE { - return new IfLetExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExpr* clone_expr_with_block_impl() const OVERRIDE { - return new IfLetExpr(*this); - } - - // Base clone function but still concrete as concrete base class - virtual IfLetExpr* clone_if_let_expr_impl() const { - return new IfLetExpr(*this); - } - }; - - // If expression with an ending "else if let" expression AST node - class IfExprConseqIfLet : public IfExpr { - // IfLetExpr* if_let_expr; - ::std::unique_ptr<IfLetExpr> if_let_expr; - - public: - /*~IfExprIfConseqIfLet() { - delete if_let_expr; - }*/ - - ::std::string as_string() const; - - IfExprConseqIfLet(::std::unique_ptr<Expr> condition, - ::std::unique_ptr<BlockExpr> if_block, ::std::unique_ptr<IfLetExpr> conseq_if_let_expr, - Location locus) : - IfExpr(::std::move(condition), ::std::move(if_block), locus), - if_let_expr(::std::move(conseq_if_let_expr)) {} - // outer attributes not allowed - - // Copy constructor with clone - IfExprConseqIfLet(IfExprConseqIfLet const& other) : - IfExpr(other), if_let_expr(other.if_let_expr->clone_if_let_expr()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to use clone - IfExprConseqIfLet& operator=(IfExprConseqIfLet const& other) { - IfExpr::operator=(other); - // condition = other.condition->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - if_let_expr = other.if_let_expr->clone_if_let_expr(); - - return *this; - } - - // move constructors - IfExprConseqIfLet(IfExprConseqIfLet&& other) = default; - IfExprConseqIfLet& operator=(IfExprConseqIfLet&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIfLet* clone_expr_impl() const OVERRIDE { - return new IfExprConseqIfLet(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIfLet* clone_expr_with_block_impl() const OVERRIDE { - return new IfExprConseqIfLet(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfExprConseqIfLet* clone_if_expr_impl() const OVERRIDE { - return new IfExprConseqIfLet(*this); - } - }; - - // AST node representing "if let" expression with an "else" expression at the end - class IfLetExprConseqElse : public IfLetExpr { - // BlockExpr* else_block; - ::std::unique_ptr<BlockExpr> else_block; - - public: - /*~IfLetExprConseqElse() { - delete else_block; - }*/ - - ::std::string as_string() const; - - IfLetExprConseqElse(::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, - ::std::unique_ptr<Expr> value, ::std::unique_ptr<BlockExpr> if_block, - ::std::unique_ptr<BlockExpr> else_block, Location locus) : - IfLetExpr( - ::std::move(match_arm_patterns), ::std::move(value), ::std::move(if_block), locus), - else_block(::std::move(else_block)) {} - // outer attributes not allowed - - // copy constructor with clone - IfLetExprConseqElse(IfLetExprConseqElse const& other) : - IfLetExpr(other), else_block(other.else_block->clone_block_expr()) {} - - // destructor - define here if required - - // overload assignment operator to clone - IfLetExprConseqElse& operator=(IfLetExprConseqElse const& other) { - IfLetExpr::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - // value = other.value->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - else_block = other.else_block->clone_block_expr(); - // outer_attrs = other.outer_attrs; - - return *this; - } - - // move constructors - IfLetExprConseqElse(IfLetExprConseqElse&& other) = default; - IfLetExprConseqElse& operator=(IfLetExprConseqElse&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqElse* clone_expr_impl() const OVERRIDE { - return new IfLetExprConseqElse(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqElse* clone_expr_with_block_impl() const OVERRIDE { - return new IfLetExprConseqElse(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqElse* clone_if_let_expr_impl() const OVERRIDE { - return new IfLetExprConseqElse(*this); - } - }; - - // AST node representing "if let" expression with an "else if" expression at the end - class IfLetExprConseqIf : public IfLetExpr { - // IfExpr* if_expr; - ::std::unique_ptr<IfExpr> if_expr; - - public: - /*~IfLetExprConseqIf() { - delete if_expr; - }*/ - - ::std::string as_string() const; - - IfLetExprConseqIf(::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, - ::std::unique_ptr<Expr> value, ::std::unique_ptr<BlockExpr> if_block, - ::std::unique_ptr<IfExpr> if_expr, Location locus) : - IfLetExpr( - ::std::move(match_arm_patterns), ::std::move(value), ::std::move(if_block), locus), - if_expr(::std::move(if_expr)) {} - // again, outer attributes not allowed - - // copy constructor with clone - IfLetExprConseqIf(IfLetExprConseqIf const& other) : - IfLetExpr(other), if_expr(other.if_expr->clone_if_expr()) {} - - // destructor - define here if required - - // overload assignment operator to clone - IfLetExprConseqIf& operator=(IfLetExprConseqIf const& other) { - IfLetExpr::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - // value = other.value->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - if_expr = other.if_expr->clone_if_expr(); - - return *this; - } - - // move constructors - IfLetExprConseqIf(IfLetExprConseqIf&& other) = default; - IfLetExprConseqIf& operator=(IfLetExprConseqIf&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIf* clone_expr_impl() const OVERRIDE { - return new IfLetExprConseqIf(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIf* clone_expr_with_block_impl() const OVERRIDE { - return new IfLetExprConseqIf(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIf* clone_if_let_expr_impl() const OVERRIDE { - return new IfLetExprConseqIf(*this); - } - }; - - // AST node representing "if let" expression with an "else if let" expression at the end - class IfLetExprConseqIfLet : public IfLetExpr { - // IfLetExpr* if_let_expr; - ::std::unique_ptr<IfLetExpr> if_let_expr; - - public: - /*~IfLetExprConseqIfLet() { - delete if_let_expr; - }*/ - - ::std::string as_string() const; - - IfLetExprConseqIfLet(::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, - ::std::unique_ptr<Expr> value, ::std::unique_ptr<BlockExpr> if_block, - ::std::unique_ptr<IfLetExpr> if_let_expr, Location locus) : - IfLetExpr( - ::std::move(match_arm_patterns), ::std::move(value), ::std::move(if_block), locus), - if_let_expr(::std::move(if_let_expr)) {} - // outer attributes not allowed - - // copy constructor with clone - IfLetExprConseqIfLet(IfLetExprConseqIfLet const& other) : - IfLetExpr(other), if_let_expr(other.if_let_expr->clone_if_let_expr()) {} - - // destructor - define here if required - - // overload assignment operator to clone - IfLetExprConseqIfLet& operator=(IfLetExprConseqIfLet const& other) { - IfLetExpr::operator=(other); - // match_arm_patterns = other.match_arm_patterns; - // value = other.value->clone_expr(); - // if_block = other.if_block->clone_block_expr(); - if_let_expr = other.if_let_expr->clone_if_let_expr(); - - return *this; - } - - // move constructors - IfLetExprConseqIfLet(IfLetExprConseqIfLet&& other) = default; - IfLetExprConseqIfLet& operator=(IfLetExprConseqIfLet&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIfLet* clone_expr_impl() const OVERRIDE { - return new IfLetExprConseqIfLet(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIfLet* clone_expr_with_block_impl() const OVERRIDE { - return new IfLetExprConseqIfLet(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual IfLetExprConseqIfLet* clone_if_let_expr_impl() const OVERRIDE { - return new IfLetExprConseqIfLet(*this); - } - }; - - // Match arm expression - struct MatchArm { - private: - ::std::vector<Attribute> outer_attrs; - // MatchArmPatterns patterns; - ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns; // inlined - - // bool has_match_arm_guard; - // Expr* match_arm_guard; // inlined from MatchArmGuard - ::std::unique_ptr<Expr> guard_expr; - - // TODO: should this store location data? - - public: - /*~MatchArm() { - if (has_match_arm_guard) { - delete match_arm_guard; - } - }*/ - - // Returns whether the MatchArm has a match arm guard expression - inline bool has_match_arm_guard() const { - return guard_expr != NULL; - } - - // Constructor for match arm with a guard expression - MatchArm(::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, - ::std::unique_ptr<Expr> guard_expr = NULL, - ::std::vector<Attribute> outer_attrs = ::std::vector<Attribute>()) : - outer_attrs(::std::move(outer_attrs)), - match_arm_patterns(::std::move(match_arm_patterns)), - guard_expr(::std::move(guard_expr)) {} - - // Copy constructor with clone - MatchArm(MatchArm const& other) : - /*match_arm_patterns(other.match_arm_patterns),*/ outer_attrs(other.outer_attrs) { - // guard to protect from null pointer dereference - if (other.guard_expr != NULL) { - guard_expr = other.guard_expr->clone_expr(); - } - - // DEBUG - fprintf( - stderr, "started copy-constructing match arm (outer attrs, guard expr done)\n"); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - - // DEBUG - fprintf(stderr, "successfully pushed back a match arm pattern\n"); - } - - // DEBUG - fprintf(stderr, "successfully copy-constructed match arm\n"); - } - - ~MatchArm() = default; - - // Overload assignment operator to clone - MatchArm& operator=(MatchArm const& other) { - // match_arm_patterns = other.match_arm_patterns; - outer_attrs = other.outer_attrs; - guard_expr = other.guard_expr->clone_expr(); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arm_patterns.reserve(other.match_arm_patterns.size()); - - for (const auto& e : other.match_arm_patterns) { - match_arm_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - MatchArm(MatchArm&& other) = default; - MatchArm& operator=(MatchArm&& other) = default; - - // Returns whether match arm is in an error state. - inline bool is_error() const { - return match_arm_patterns.empty(); - } - - // Creates a match arm in an error state. - static MatchArm create_error() { - return MatchArm(::std::vector< ::std::unique_ptr<Pattern> >()); - } - - ::std::string as_string() const; - }; - - // Base "match case" for a match expression - abstract - class MatchCase { - MatchArm arm; - - protected: - MatchCase(MatchArm arm) : arm(::std::move(arm)) {} - - // Should not require copy constructor or assignment operator overloading - - // Clone function implementation as pure virtual method - virtual MatchCase* clone_match_case_impl() const = 0; - - public: - virtual ~MatchCase() {} - - // Unique pointer custom clone function - ::std::unique_ptr<MatchCase> clone_match_case() const { - // DEBUG - fprintf(stderr, "about to call clone match case impl\n"); - - return ::std::unique_ptr<MatchCase>(clone_match_case_impl()); - } - - virtual ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) = 0; - }; - - // Block expression match case - class MatchCaseBlockExpr : public MatchCase { - // BlockExpr* block_expr; - ::std::unique_ptr<BlockExpr> block_expr; - - // TODO: should this store location data? - - public: - /*~MatchCaseBlockExpr() { - delete block_expr; - }*/ - - MatchCaseBlockExpr(MatchArm arm, ::std::unique_ptr<BlockExpr> block_expr) : - MatchCase(::std::move(arm)), block_expr(::std::move(block_expr)) {} - - // Copy constructor requires clone - MatchCaseBlockExpr(MatchCaseBlockExpr const& other) : - MatchCase(other), block_expr(other.block_expr->clone_block_expr()) { - // DEBUG - fprintf(stderr, "successfully copy constructed match case expr\n"); - } - - // Destructor - define here if required - - // Overload assignment operator to have clone - MatchCaseBlockExpr& operator=(MatchCaseBlockExpr const& other) { - MatchCase::operator=(other); - block_expr = other.block_expr->clone_block_expr(); - // arm = other.arm; - - return *this; - } - - // move constructors - MatchCaseBlockExpr(MatchCaseBlockExpr&& other) = default; - MatchCaseBlockExpr& operator=(MatchCaseBlockExpr&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MatchCaseBlockExpr* clone_match_case_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "about to copy construct match case block expr\n"); - - return new MatchCaseBlockExpr(*this); - } - }; - - // Expression (except block expression) match case - class MatchCaseExpr : public MatchCase { - // Expr* expr; - ::std::unique_ptr<Expr> expr; - - // TODO: should this store location data? - - public: - /*~MatchCaseExpr() { - delete expr; - }*/ - - MatchCaseExpr(MatchArm arm, ::std::unique_ptr<Expr> expr) : - MatchCase(::std::move(arm)), expr(::std::move(expr)) {} - - // Copy constructor requires clone - MatchCaseExpr(MatchCaseExpr const& other) : - MatchCase(other), expr(other.expr->clone_expr()) { - // DEBUG - fprintf(stderr, "successfully copy constructed match case expr\n"); - } - - // Destructor - define here if required +namespace AST { +/* TODO: if GCC moves to C++17 or allows boost, replace some boolean + * "has_whatever" pairs with + * optional types (std::optional or boost::optional)? */ + +// forward decls: defined in rust-path.h, rust-type.h, rust-pattern.h, and +// rust-stmt.h +/*class PathInExpression; +class QualifiedPathInExpression; +class PathExprSegment;*/ // decls no longer required as "rust-path.h" is included +/*class Type; +class TypeNoBounds; +class Lifetime; +class Pattern; +class Statement;*/ // decls no longer required as definitions moved to rust-ast.h + +// Decl as definition moved to rust-ast.h +class ExprWithoutBlock; + +// AST node for an expression with an accompanying block - abstract +class ExprWithBlock : public Expr +{ + // TODO: should this mean that a BlockExpr should be a member variable? +protected: + ExprWithBlock (::std::vector<Attribute> outer_attrs + = ::std::vector<Attribute> ()) + : Expr (::std::move (outer_attrs)) + {} + + // pure virtual clone implementation + virtual ExprWithBlock *clone_expr_with_block_impl () const = 0; + + // prevent having to define multiple clone expressions + virtual ExprWithBlock *clone_expr_impl () const OVERRIDE + { + return clone_expr_with_block_impl (); + } + +public: + // Unique pointer custom clone function + ::std::unique_ptr<ExprWithBlock> clone_expr_with_block () const + { + return ::std::unique_ptr<ExprWithBlock> (clone_expr_with_block_impl ()); + } +}; + +// Literals? Or literal base? +class LiteralExpr : public ExprWithoutBlock +{ + /*public: + enum LitType { + CHAR, + STRING, + RAW_STRING, + BYTE, + BYTE_STRING, + RAW_BYTE_STRING, + INT, + FLOAT, + BOOL + }; + + private: + // TODO: maybe make subclasses of each type of literal with their typed + values (or + // generics) + ::std::string value_as_string; + LitType type;*/ + // moved to Literal + Literal literal; + + Location locus; + +public: + ::std::string as_string () const { return literal.as_string (); } + + inline Literal::LitType get_lit_type () const + { + return literal.get_lit_type (); + } + + LiteralExpr (::std::string value_as_string, Literal::LitType type, + Location locus, + ::std::vector<Attribute> outer_attrs + = ::std::vector<Attribute> ()) + : ExprWithoutBlock (::std::move (outer_attrs)), + literal (::std::move (value_as_string), type), locus (locus) + {} + + LiteralExpr (Literal literal, Location locus, + ::std::vector<Attribute> outer_attrs + = ::std::vector<Attribute> ()) + : ExprWithoutBlock (::std::move (outer_attrs)), + literal (::std::move (literal)), locus (locus) + {} + + // Unique pointer custom clone function + ::std::unique_ptr<LiteralExpr> clone_literal_expr () const + { + return ::std::unique_ptr<LiteralExpr> (clone_literal_expr_impl ()); + } + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual LiteralExpr *clone_expr_impl () const OVERRIDE + { + return new LiteralExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual LiteralExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new LiteralExpr (*this); + } + + // not virtual as currently no subclasses of LiteralExpr, but could be in + // future + /*virtual*/ LiteralExpr *clone_literal_expr_impl () const + { + return new LiteralExpr (*this); + } +}; + +// Literal expression attribute body (non-macro attribute) +class AttrInputLiteral : public AttrInput +{ + // Literal expression WITHOUT SUFFIX + // LiteralExpr* literal_expr; + //::std::unique_ptr<LiteralExpr> literal_expr; + LiteralExpr + literal_expr; // as not using polymorphic behaviour, doesn't require pointer + // TODO: will require pointer if LiteralExpr is changed to have subclassing + + // TODO: should this store location data? + +public: + AttrInputLiteral (LiteralExpr lit_expr) + : literal_expr (::std::move (lit_expr)) + {} + /*~AttrInputLiteral() { + delete literal_expr; + }*/ + + ::std::string as_string () const { return " = " + literal_expr.as_string (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + // this can never be a cfg predicate - cfg and cfg_attr require a token-tree + // cfg + virtual bool + check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const OVERRIDE + { + // TODO: ensure this is true + // DEBUG + fprintf (stderr, "check_cfg_predicate call went to AttrInputLiteral - " + "should not happen?\n"); + + return false; + } + +protected: + // Use covariance to implement clone function as returning an AttrInputLiteral + // object + virtual AttrInputLiteral *clone_attr_input_impl () const OVERRIDE + { + return new AttrInputLiteral (*this); + } +}; + +// literal expr only meta item inner - TODO possibly replace with inheritance of +// LiteralExpr itself? +class MetaItemLitExpr : public MetaItemInner +{ + LiteralExpr lit_expr; + +public: + MetaItemLitExpr (LiteralExpr lit_expr) : lit_expr (::std::move (lit_expr)) {} + + ::std::string as_string () const OVERRIDE { return lit_expr.as_string (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + virtual bool check_cfg_predicate (const Session &session) const OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this type + virtual MetaItemLitExpr *clone_meta_item_inner_impl () const OVERRIDE + { + return new MetaItemLitExpr (*this); + } +}; + +// more generic meta item "path = lit" form +class MetaItemPathLit : public MetaItem +{ + SimplePath path; + LiteralExpr lit; + +public: + MetaItemPathLit (SimplePath path, LiteralExpr lit_expr) + : path (::std::move (path)), lit (::std::move (lit_expr)) + {} + + ::std::string as_string () const OVERRIDE + { + return path.as_string () + " = " + lit.as_string (); + } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + virtual bool check_cfg_predicate (const Session &session) const OVERRIDE; + // TODO: return true if "ident" is defined and value of it is "lit", return + // false otherwise + +protected: + // Use covariance to implement clone function as returning this type + virtual MetaItemPathLit *clone_meta_item_inner_impl () const OVERRIDE + { + return new MetaItemPathLit (*this); + } +}; + +// AST node for a non-qualified path expression - FIXME: should this be +// inheritance instead? +/*class PathExprNonQual : public PathExpr { + PathInExpression path; + + public: + ::std::string as_string() const { + return path.as_string(); + } - // Overload assignment operator to have clone - MatchCaseExpr& operator=(MatchCaseExpr const& other) { - MatchCase::operator=(other); - expr = other.expr->clone_expr(); - // arm = other.arm; + PathExprNonQual(PathInExpression path, ::std::vector<Attribute> +outer_attribs) : PathExpr(::std::move(outer_attribs)), path(::std::move(path)) +{} - return *this; - } + protected: + // Use covariance to implement clone function as returning this object +rather than base virtual PathExprNonQual* clone_expr_impl() const OVERRIDE { + return new PathExprNonQual(*this); + } - // move constructors - MatchCaseExpr(MatchCaseExpr&& other) = default; - MatchCaseExpr& operator=(MatchCaseExpr&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + // Use covariance to implement clone function as returning this object +rather than base virtual PathExprNonQual* clone_expr_without_block_impl() const +OVERRIDE { return new PathExprNonQual(*this); + } +};*/ +// converted to inheritance - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MatchCaseExpr* clone_match_case_impl() const OVERRIDE { - // DEBUG - fprintf(stderr, "about to copy construct match case expr\n"); - if (expr == NULL) { - fprintf( - stderr, "warning: match case expr to be copy constructed has null expr!\n"); - } - - return new MatchCaseExpr(*this); - } - }; - - // Match expression AST node - class MatchExpr : public ExprWithBlock { - // Expr* branch_value; - ::std::unique_ptr<Expr> branch_value; - ::std::vector<Attribute> inner_attrs; - - // bool has_match_arms; - // MatchArms match_arms; - ::std::vector< ::std::unique_ptr<MatchCase> > match_arms; // inlined from MatchArms - - Location locus; - - public: - /*~MatchExpr() { - delete branch_value; - }*/ - - ::std::string as_string() const; - - // Returns whether the match expression has any match arms. - inline bool has_match_arms() const { - return !match_arms.empty(); - } - - MatchExpr(::std::unique_ptr<Expr> branch_value, - ::std::vector< ::std::unique_ptr<MatchCase> > match_arms, - ::std::vector<Attribute> inner_attrs, ::std::vector<Attribute> outer_attrs, - Location locus) : - ExprWithBlock(::std::move(outer_attrs)), - branch_value(::std::move(branch_value)), inner_attrs(::std::move(inner_attrs)), - match_arms(::std::move(match_arms)), locus(locus) {} - - // Copy constructor requires clone due to unique_ptr - MatchExpr(MatchExpr const& other) : - ExprWithBlock(other), - branch_value(other.branch_value->clone_expr()), /*match_arms(other.match_arms),*/ - inner_attrs(other.inner_attrs), locus(other.locus) { - fprintf(stderr, "copy constructor for matchexpr called - only match arm vector " - "copying after this\n"); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arms.reserve(other.match_arms.size()); - - fprintf(stderr, "match expr: successfully reserved size\n"); - - for (const auto& e : other.match_arms) { - match_arms.push_back(e->clone_match_case()); - fprintf(stderr, "match expr: successfully pushed back a match case\n"); - } - - fprintf(stderr, "match expr: successfully pushed back all match cases\n"); - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone due to unique_ptr - MatchExpr& operator=(MatchExpr const& other) { - ExprWithBlock::operator=(other); - branch_value = other.branch_value->clone_expr(); - // match_arms = other.match_arms; - inner_attrs = other.inner_attrs; - // outer_attrs = other.outer_attrs; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - match_arms.reserve(other.match_arms.size()); - - for (const auto& e : other.match_arms) { - match_arms.push_back(e->clone_match_case()); - } - - return *this; - } - - // move constructors - MatchExpr(MatchExpr&& other) = default; - MatchExpr& operator=(MatchExpr&& other) = default; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MatchExpr* clone_expr_impl() const OVERRIDE { - return new MatchExpr(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MatchExpr* clone_expr_with_block_impl() const OVERRIDE { - return new MatchExpr(*this); - } - }; - - // Await expression AST node (pseudo-member variable access) - class AwaitExpr : public ExprWithoutBlock { - ::std::unique_ptr<Expr> awaited_expr; - - Location locus; - - public: - // TODO: ensure outer attributes are actually allowed - AwaitExpr(::std::unique_ptr<Expr> awaited_expr, ::std::vector<Attribute> outer_attrs, - Location locus) : - ExprWithoutBlock(::std::move(outer_attrs)), - awaited_expr(::std::move(awaited_expr)), locus(locus) {} - - // copy constructor with clone - AwaitExpr(AwaitExpr const& other) : - ExprWithoutBlock(other), awaited_expr(other.awaited_expr->clone_expr()), - locus(other.locus) {} - - // destructor - define here if required - - // overloaded assignment operator with clone - AwaitExpr& operator=(AwaitExpr const& other) { - ExprWithoutBlock::operator=(other); - awaited_expr = other.awaited_expr->clone_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - AwaitExpr(AwaitExpr&& other) = default; - AwaitExpr& operator=(AwaitExpr&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } +// AST node for a qualified path expression - FIXME: should this be inheritance +// instead? +/*class PathExprQual : public PathExpr { + QualifiedPathInExpression path; - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } + public: + ::std::string as_string() const { + return path.as_string(); + } - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual AwaitExpr* clone_expr_without_block_impl() const OVERRIDE { - return new AwaitExpr(*this); - } - }; - - // Async block expression AST node (block expr that evaluates to a future) - class AsyncBlockExpr : public ExprWithBlock { - // TODO: should this extend BlockExpr rather than be a composite of it? - bool has_move; - ::std::unique_ptr<BlockExpr> block_expr; - - Location locus; - - public: - AsyncBlockExpr(::std::unique_ptr<BlockExpr> block_expr, bool has_move, - ::std::vector<Attribute> outer_attrs, Location locus) : - ExprWithBlock(::std::move(outer_attrs)), - has_move(has_move), block_expr(::std::move(block_expr)), locus(locus) {} - - // copy constructor with clone - AsyncBlockExpr(AsyncBlockExpr const& other) : - ExprWithBlock(other), has_move(other.has_move), - block_expr(other.block_expr->clone_block_expr()), locus(other.locus) {} + PathExprQual(QualifiedPathInExpression path, ::std::vector<Attribute> +outer_attribs) : PathExpr(::std::move(outer_attribs)), path(::std::move(path)) +{} - // destructor - define if required - - // overloaded assignment operator to clone - AsyncBlockExpr& operator=(AsyncBlockExpr const& other) { - ExprWithBlock::operator=(other); - has_move = other.has_move; - block_expr = other.block_expr->clone_block_expr(); - locus = other.locus; - - return *this; - } - - // move constructors - AsyncBlockExpr(AsyncBlockExpr&& other) = default; - AsyncBlockExpr& operator=(AsyncBlockExpr&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; + protected: + // Use covariance to implement clone function as returning this object +rather than base virtual PathExprQual* clone_expr_impl() const OVERRIDE { return +new PathExprQual(*this); + } - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual AsyncBlockExpr* clone_expr_with_block_impl() const OVERRIDE { - return new AsyncBlockExpr(*this); - } - }; + // Use covariance to implement clone function as returning this object +rather than base virtual PathExprQual* clone_expr_without_block_impl() const +OVERRIDE { return new PathExprQual(*this); } -} +};*/ +// replaced with inheritance + +// Represents an expression using unary or binary operators as AST node. Can be +// overloaded. +class OperatorExpr : public ExprWithoutBlock +{ + // TODO: create binary and unary operator subclasses? + + Location locus; + +protected: + // Variable must be protected to allow derived classes to use it as a first + // class citizen Expr* main_or_left_expr; + ::std::unique_ptr<Expr> main_or_left_expr; + + // Constructor (only for initialisation of expr purposes) + OperatorExpr (::std::unique_ptr<Expr> main_or_left_expr, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), locus (locus), + main_or_left_expr (::std::move (main_or_left_expr)) + {} + + // Copy constructor (only for initialisation of expr purposes) + OperatorExpr (OperatorExpr const &other) + : ExprWithoutBlock (other), + locus ( + other + .locus) /*, main_or_left_expr(other.main_or_left_expr->clone_expr())*/ + { + // DEBUG: moved main_or_left_expr into body - move back later + + if (other.main_or_left_expr == NULL) + { + fprintf (stderr, "other operator expr's main_or_left_expr is null!\n"); + } + + fprintf (stderr, "called operator expr copy constructor - about to clone " + "main_or_left_expr\n"); + main_or_left_expr = other.main_or_left_expr->clone_expr (); + fprintf (stderr, "successfully cloned main_or_left_expr\n"); + // this occurred successfully, so something else must be the issue + } + + // Overload assignment operator to deep copy expr + OperatorExpr &operator= (OperatorExpr const &other) + { + ExprWithoutBlock::operator= (other); + main_or_left_expr = other.main_or_left_expr->clone_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + OperatorExpr (OperatorExpr &&other) = default; + OperatorExpr &operator= (OperatorExpr &&other) = default; + +public: + /*virtual ~OperatorExpr() { + delete main_or_left_expr; + }*/ + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } +}; + +// Unary prefix & or &mut (or && and &&mut) borrow operator. Cannot be +// overloaded. +class BorrowExpr : public OperatorExpr +{ + bool is_mut; + bool double_borrow; + +public: + ::std::string as_string () const; + + BorrowExpr (::std::unique_ptr<Expr> borrow_lvalue, bool is_mut_borrow, + bool is_double_borrow, ::std::vector<Attribute> outer_attribs, + Location locus) + : OperatorExpr (::std::move (borrow_lvalue), ::std::move (outer_attribs), + locus), + is_mut (is_mut_borrow), double_borrow (is_double_borrow) + {} + + // Copy constructor - define here if required + + // Destructor - define here if required + + // Overload assignment operator here if required + + // Move semantics here if required + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual BorrowExpr *clone_expr_impl () const OVERRIDE + { + return new BorrowExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual BorrowExpr *clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf (stderr, "called clone_expr_without_block_impl() on borrowexpr\n"); + + return new BorrowExpr (*this); + } +}; + +// Unary prefix * deference operator +class DereferenceExpr : public OperatorExpr +{ +public: + ::std::string as_string () const; + + // Constructor calls OperatorExpr's protected constructor + DereferenceExpr (::std::unique_ptr<Expr> deref_lvalue, + ::std::vector<Attribute> outer_attribs, Location locus) + : OperatorExpr (::std::move (deref_lvalue), ::std::move (outer_attribs), + locus) + {} + + // Copy constructor - define here if required + + // Destructor - define here if required + + // Overload assignment operator here if required + + // Move semantics here if required + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual DereferenceExpr *clone_expr_impl () const OVERRIDE + { + return new DereferenceExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual DereferenceExpr *clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf (stderr, + "called clone_expr_without_block_impl() on dereferenceexpr\n"); + + return new DereferenceExpr (*this); + } +}; + +// Unary postfix ? error propogation operator. Cannot be overloaded. +class ErrorPropagationExpr : public OperatorExpr +{ +public: + ::std::string as_string () const; + + // Constructor calls OperatorExpr's protected constructor + ErrorPropagationExpr (::std::unique_ptr<Expr> potential_error_value, + ::std::vector<Attribute> outer_attribs, Location locus) + : OperatorExpr (::std::move (potential_error_value), + ::std::move (outer_attribs), locus) + {} + + // Copy constructor - define here if required + + // Destructor - define here if required + + // Overload assignment operator here if required + + // Move semantics here if required + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ErrorPropagationExpr *clone_expr_impl () const OVERRIDE + { + return new ErrorPropagationExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ErrorPropagationExpr *clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf ( + stderr, + "called clone_expr_without_block_impl() on errorpropagationexpr\n"); + + return new ErrorPropagationExpr (*this); + } +}; + +// Unary prefix - or ! negation or NOT operators. +class NegationExpr : public OperatorExpr +{ +public: + enum NegationType + { + NEGATE, + NOT + }; + +private: + // Note: overload negation via std::ops::Neg and not via std::ops::Not + // Negation only works for signed integer and floating-point types, NOT only + // works for boolean and integer types (via bitwise NOT) + NegationType negation_type; + +public: + ::std::string as_string () const; + + inline NegationType get_negation_type () const { return negation_type; } + + // Constructor calls OperatorExpr's protected constructor + NegationExpr (::std::unique_ptr<Expr> negated_value, + NegationType negation_kind, + ::std::vector<Attribute> outer_attribs, Location locus) + : OperatorExpr (::std::move (negated_value), ::std::move (outer_attribs), + locus), + negation_type (negation_kind) + {} + + // Copy constructor - define here if required + + // Destructor - define here if required + + // Overload assignment operator here if required + + // Move semantics here if required + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual NegationExpr *clone_expr_impl () const OVERRIDE + { + return new NegationExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual NegationExpr *clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf (stderr, + "called clone_expr_without_block_impl() on negationexpr\n"); + + return new NegationExpr (*this); + } +}; + +// Infix binary operators. +, -, *, /, %, &, |, ^, <<, >> +class ArithmeticOrLogicalExpr : public OperatorExpr +{ +public: + enum ExprType + { + ADD, // std::ops::Add + SUBTRACT, // std::ops::Sub + MULTIPLY, // std::ops::Mul + DIVIDE, // std::ops::Div + MODULUS, // std::ops::Rem + BITWISE_AND, // std::ops::BitAnd + BITWISE_OR, // std::ops::BitOr + BITWISE_XOR, // std::ops::BitXor + LEFT_SHIFT, // std::ops::Shl + RIGHT_SHIFT // std::ops::Shr + }; + +private: + // Note: overloading trait specified in comments + ExprType expr_type; + + // Expr* right_expr; + ::std::unique_ptr<Expr> right_expr; + +public: + /*~ArithmeticOrLogicalExpr() { + delete right_expr; + }*/ + + ::std::string as_string () const; + + inline ExprType get_expr_type () const { return expr_type; } + + // Constructor calls OperatorExpr's protected constructor + ArithmeticOrLogicalExpr (::std::unique_ptr<Expr> left_value, + ::std::unique_ptr<Expr> right_value, + ExprType expr_kind, Location locus) + : OperatorExpr (::std::move (left_value), ::std::vector<Attribute> (), + locus), + expr_type (expr_kind), right_expr (::std::move (right_value)) + {} + // outer attributes not allowed + + // Copy constructor - probably required due to unique pointer + ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr const &other) + : OperatorExpr (other), expr_type (other.expr_type), + right_expr (other.right_expr->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator + ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + expr_type = other.expr_type; + + return *this; + } + + // move constructors + ArithmeticOrLogicalExpr (ArithmeticOrLogicalExpr &&other) = default; + ArithmeticOrLogicalExpr &operator= (ArithmeticOrLogicalExpr &&other) + = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ArithmeticOrLogicalExpr *clone_expr_impl () const OVERRIDE + { + return new ArithmeticOrLogicalExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ArithmeticOrLogicalExpr * + clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf ( + stderr, + "called clone_expr_without_block_impl() on arithmeticorlogicalexpr\n"); + + return new ArithmeticOrLogicalExpr (*this); + } +}; + +// Infix binary comparison operators. ==, !=, <, <=, >, >= +class ComparisonExpr : public OperatorExpr +{ +public: + enum ExprType + { + EQUAL, // std::cmp::PartialEq::eq + NOT_EQUAL, // std::cmp::PartialEq::ne + GREATER_THAN, // std::cmp::PartialEq::gt + LESS_THAN, // std::cmp::PartialEq::lt + GREATER_OR_EQUAL, // std::cmp::PartialEq::ge + LESS_OR_EQUAL // std::cmp::PartialEq::le + }; + +private: + // Note: overloading trait specified in comments + ExprType expr_type; + + // Expr* right_expr; + ::std::unique_ptr<Expr> right_expr; + +public: + /*~ComparisonExpr() { + delete right_expr; + }*/ + + ::std::string as_string () const; + + inline ExprType get_expr_type () const { return expr_type; } + + // Constructor requires pointers for polymorphism + ComparisonExpr (::std::unique_ptr<Expr> left_value, + ::std::unique_ptr<Expr> right_value, ExprType comparison_kind, + Location locus) + : OperatorExpr (::std::move (left_value), ::std::vector<Attribute> (), + locus), + expr_type (comparison_kind), right_expr (::std::move (right_value)) + {} + // outer attributes not allowed + + // Copy constructor also calls OperatorExpr's protected constructor + ComparisonExpr (ComparisonExpr const &other) + : OperatorExpr (other), expr_type (other.expr_type), + right_expr (other.right_expr->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to deep copy + ComparisonExpr &operator= (ComparisonExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + expr_type = other.expr_type; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ComparisonExpr (ComparisonExpr &&other) = default; + ComparisonExpr &operator= (ComparisonExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + // TODO: implement via a function call to std::cmp::PartialEq::eq(&op1, &op2) + // maybe? +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ComparisonExpr *clone_expr_impl () const OVERRIDE + { + return new ComparisonExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ComparisonExpr *clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf (stderr, + "called clone_expr_without_block_impl() on comparisonexpr\n"); + + return new ComparisonExpr (*this); + } +}; + +// Infix binary lazy boolean logical operators && and ||. +class LazyBooleanExpr : public OperatorExpr +{ +public: + enum ExprType + { + LOGICAL_OR, + LOGICAL_AND + }; + +private: + ExprType expr_type; + + // Expr* right_expr; + ::std::unique_ptr<Expr> right_expr; + +public: + /*~LazyBooleanExpr() { + delete right_expr; + }*/ + + // Constructor calls OperatorExpr's protected constructor + LazyBooleanExpr (::std::unique_ptr<Expr> left_bool_expr, + ::std::unique_ptr<Expr> right_bool_expr, ExprType expr_kind, + Location locus) + : OperatorExpr (::std::move (left_bool_expr), ::std::vector<Attribute> (), + locus), + expr_type (expr_kind), right_expr (::std::move (right_bool_expr)) + {} + // outer attributes not allowed + + // Copy constructor also calls OperatorExpr's protected constructor + LazyBooleanExpr (LazyBooleanExpr const &other) + : OperatorExpr (other), expr_type (other.expr_type), + right_expr (other.right_expr->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to deep copy + LazyBooleanExpr &operator= (LazyBooleanExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + expr_type = other.expr_type; + + return *this; + } + + // move constructors + LazyBooleanExpr (LazyBooleanExpr &&other) = default; + LazyBooleanExpr &operator= (LazyBooleanExpr &&other) = default; + + ::std::string as_string () const; + + inline ExprType get_expr_type () const { return expr_type; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual LazyBooleanExpr *clone_expr_impl () const OVERRIDE + { + return new LazyBooleanExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual LazyBooleanExpr *clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf (stderr, + "called clone_expr_without_block_impl() on lazybooleanexpr\n"); + + return new LazyBooleanExpr (*this); + } +}; + +// Binary infix "as" cast expression. +class TypeCastExpr : public OperatorExpr +{ + // TypeNoBounds type_to_convert_to; + ::std::unique_ptr<TypeNoBounds> type_to_convert_to; + + // Note: only certain type casts allowed, outlined in reference +public: + ::std::string as_string () const; + + // Constructor requires calling protected constructor of OperatorExpr + TypeCastExpr (::std::unique_ptr<Expr> expr_to_cast, + ::std::unique_ptr<TypeNoBounds> type_to_cast_to, Location locus) + : OperatorExpr (::std::move (expr_to_cast), ::std::vector<Attribute> (), + locus), + type_to_convert_to (::std::move (type_to_cast_to)) + {} + // outer attributes not allowed + + // Copy constructor also requires calling protected constructor + TypeCastExpr (TypeCastExpr const &other) + : OperatorExpr (other), + type_to_convert_to (other.type_to_convert_to->clone_type_no_bounds ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to deep copy + TypeCastExpr &operator= (TypeCastExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + type_to_convert_to = other.type_to_convert_to->clone_type_no_bounds (); + + return *this; + } + + // move constructors as not supported in c++03 + TypeCastExpr (TypeCastExpr &&other) = default; + TypeCastExpr &operator= (TypeCastExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TypeCastExpr *clone_expr_impl () const OVERRIDE + { + return new TypeCastExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual TypeCastExpr *clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf (stderr, + "called clone_expr_without_block_impl() on typecastexpr\n"); + + return new TypeCastExpr (*this); + } +}; + +// Binary assignment expression. +class AssignmentExpr : public OperatorExpr +{ + // Expr* right_expr; + ::std::unique_ptr<Expr> right_expr; + +public: + /*~AssignmentExpr() { + delete right_expr; + }*/ + + ::std::string as_string () const; + + // Call OperatorExpr constructor to initialise left_expr + AssignmentExpr (::std::unique_ptr<Expr> value_to_assign_to, + ::std::unique_ptr<Expr> value_to_assign, Location locus) + : OperatorExpr (::std::move (value_to_assign_to), + ::std::vector<Attribute> (), locus), + right_expr (::std::move (value_to_assign)) + {} + // outer attributes not allowed + + // Call OperatorExpr constructor in copy constructor, as well as clone + AssignmentExpr (AssignmentExpr const &other) + : OperatorExpr (other) /*, right_expr(other.right_expr->clone_expr())*/ + { + // DEBUG: moved cloning right expr into body + fprintf (stderr, "assignment expr copy constructor successfully cloned " + "base operator expr\n"); + if (other.right_expr == NULL) + { + fprintf (stderr, "other expr's right expr (in assignment) is null!!!"); + } + fprintf (stderr, "test other's right expr as string: %s\n", + other.right_expr->as_string ().c_str ()); + // apparently, despite not being null, cloning still fails + right_expr = other.right_expr->clone_expr (); + fprintf ( + stderr, + "assignment expr copy constructor successfully cloned right expr\n"); + + // DEBUG + fprintf (stderr, "assignment expr copy constructor called successfully\n"); + } + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr right_expr + AssignmentExpr &operator= (AssignmentExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + AssignmentExpr (AssignmentExpr &&other) = default; + AssignmentExpr &operator= (AssignmentExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual AssignmentExpr *clone_expr_impl () const OVERRIDE + { + return new AssignmentExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual AssignmentExpr *clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf (stderr, + "called clone_expr_without_block_impl() on assignmentexpr\n"); + + return new AssignmentExpr (*this); + } +}; + +// Binary infix compound assignment (arithmetic or logic then assignment) +// expressions. +class CompoundAssignmentExpr : public OperatorExpr +{ +public: + enum ExprType + { + ADD, // std::ops::AddAssign + SUBTRACT, // std::ops::SubAssign + MULTIPLY, // std::ops::MulAssign + DIVIDE, // std::ops::DivAssign + MODULUS, // std::ops::RemAssign + BITWISE_AND, // std::ops::BitAndAssign + BITWISE_OR, // std::ops::BitOrAssign + BITWISE_XOR, // std::ops::BitXorAssign + LEFT_SHIFT, // std::ops::ShlAssign + RIGHT_SHIFT // std::ops::ShrAssign + }; + +private: + // Note: overloading trait specified in comments + ExprType expr_type; + + // Expr* right_expr; + ::std::unique_ptr<Expr> right_expr; + +public: + /*~CompoundAssignmentExpr() { + delete right_expr; + }*/ + + ::std::string as_string () const; + + inline ExprType get_expr_type () const { return expr_type; } + + // Use pointers in constructor to enable polymorphism + CompoundAssignmentExpr (::std::unique_ptr<Expr> value_to_assign_to, + ::std::unique_ptr<Expr> value_to_assign, + ExprType expr_kind, Location locus) + : OperatorExpr (::std::move (value_to_assign_to), + ::std::vector<Attribute> (), locus), + expr_type (expr_kind), right_expr (::std::move (value_to_assign)) + {} + // outer attributes not allowed + + // Have clone in copy constructor + CompoundAssignmentExpr (CompoundAssignmentExpr const &other) + : OperatorExpr (other), expr_type (other.expr_type), + right_expr (other.right_expr->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone + CompoundAssignmentExpr &operator= (CompoundAssignmentExpr const &other) + { + OperatorExpr::operator= (other); + // main_or_left_expr = other.main_or_left_expr->clone_expr(); + right_expr = other.right_expr->clone_expr (); + expr_type = other.expr_type; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + CompoundAssignmentExpr (CompoundAssignmentExpr &&other) = default; + CompoundAssignmentExpr &operator= (CompoundAssignmentExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual CompoundAssignmentExpr *clone_expr_impl () const OVERRIDE + { + return new CompoundAssignmentExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual CompoundAssignmentExpr * + clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf ( + stderr, + "called clone_expr_without_block_impl() on compoundassignmentexpr\n"); + + return new CompoundAssignmentExpr (*this); + } +}; + +// Expression in parentheses (i.e. like literally just any 3 + (2 * 6)) +class GroupedExpr : public ExprWithoutBlock +{ + ::std::vector<Attribute> inner_attrs; + // Expr* expr_in_parens; + ::std::unique_ptr<Expr> expr_in_parens; + + Location locus; + +public: + /*~GroupedExpr() { + delete expr_in_parens; + }*/ + + ::std::string as_string () const; + + inline ::std::vector<Attribute> get_inner_attrs () const + { + return inner_attrs; + } + + GroupedExpr (::std::unique_ptr<Expr> parenthesised_expr, + ::std::vector<Attribute> inner_attribs, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), + inner_attrs (::std::move (inner_attribs)), + expr_in_parens (::std::move (parenthesised_expr)), locus (locus) + {} + + // Copy constructor includes clone for expr_in_parens + GroupedExpr (GroupedExpr const &other) + : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), + expr_in_parens (other.expr_in_parens->clone_expr ()), locus (other.locus) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone expr_in_parens + GroupedExpr &operator= (GroupedExpr const &other) + { + ExprWithoutBlock::operator= (other); + inner_attrs = other.inner_attrs; + expr_in_parens = other.expr_in_parens->clone_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + GroupedExpr (GroupedExpr &&other) = default; + GroupedExpr &operator= (GroupedExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual GroupedExpr *clone_expr_impl () const OVERRIDE + { + return new GroupedExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual GroupedExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new GroupedExpr (*this); + } +}; + +// Base array initialisation internal element representation thing (abstract) +// aka ArrayElements +class ArrayElems +{ +public: + virtual ~ArrayElems () {} + + // Unique pointer custom clone ArrayElems function + ::std::unique_ptr<ArrayElems> clone_array_elems () const + { + return ::std::unique_ptr<ArrayElems> (clone_array_elems_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // pure virtual clone implementation + virtual ArrayElems *clone_array_elems_impl () const = 0; +}; + +// Value array elements +class ArrayElemsValues : public ArrayElems +{ + //::std::vector<Expr> values; + ::std::vector< ::std::unique_ptr<Expr> > values; + + // TODO: should this store location data? + +public: + /*inline ::std::vector< ::std::unique_ptr<Expr> > get_values() const { + return values; + }*/ + + ArrayElemsValues (::std::vector< ::std::unique_ptr<Expr> > elems) + : values (::std::move (elems)) + {} + + // copy constructor with vector clone + ArrayElemsValues (ArrayElemsValues const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + values.reserve (other.values.size ()); + + for (const auto &e : other.values) + { + values.push_back (e->clone_expr ()); + } + } + + // overloaded assignment operator with vector clone + ArrayElemsValues &operator= (ArrayElemsValues const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + values.reserve (other.values.size ()); + + for (const auto &e : other.values) + { + values.push_back (e->clone_expr ()); + } + + return *this; + } + + // move constructors + ArrayElemsValues (ArrayElemsValues &&other) = default; + ArrayElemsValues &operator= (ArrayElemsValues &&other) = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + virtual ArrayElemsValues *clone_array_elems_impl () const OVERRIDE + { + return new ArrayElemsValues (*this); + } +}; + +// Copied array element and number of copies +class ArrayElemsCopied : public ArrayElems +{ + // Expr* elem_to_copy; + ::std::unique_ptr<Expr> elem_to_copy; + // Expr* num_copies; + ::std::unique_ptr<Expr> num_copies; + + // TODO: should this store location data? + +public: + /*~ArrayElemsCopied() { + delete num_copies; + delete elem_to_copy; + }*/ + + // Constructor requires pointers for polymorphism + ArrayElemsCopied (::std::unique_ptr<Expr> copied_elem, + ::std::unique_ptr<Expr> copy_amount) + : elem_to_copy (::std::move (copied_elem)), + num_copies (::std::move (copy_amount)) + {} + + // Copy constructor required due to unique_ptr - uses custom clone + ArrayElemsCopied (ArrayElemsCopied const &other) + : elem_to_copy (other.elem_to_copy->clone_expr ()), + num_copies (other.num_copies->clone_expr ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator for deep copying + ArrayElemsCopied &operator= (ArrayElemsCopied const &other) + { + elem_to_copy = other.elem_to_copy->clone_expr (); + num_copies = other.num_copies->clone_expr (); + + return *this; + } + + // move constructors + ArrayElemsCopied (ArrayElemsCopied &&other) = default; + ArrayElemsCopied &operator= (ArrayElemsCopied &&other) = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + virtual ArrayElemsCopied *clone_array_elems_impl () const OVERRIDE + { + return new ArrayElemsCopied (*this); + } +}; + +// Array definition-ish expression +class ArrayExpr : public ExprWithoutBlock +{ + ::std::vector<Attribute> inner_attrs; + // ArrayElems internal_elements; + ::std::unique_ptr<ArrayElems> internal_elements; + + Location locus; + +public: + ::std::string as_string () const; + + inline ::std::vector<Attribute> get_inner_attrs () const + { + return inner_attrs; + } + + // Returns whether array expr has array elems or if it is just empty. + inline bool has_array_elems () const { return internal_elements != NULL; } + + // Constructor requires ArrayElems pointer + ArrayExpr (::std::unique_ptr<ArrayElems> array_elems, + ::std::vector<Attribute> inner_attribs, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), + inner_attrs (::std::move (inner_attribs)), + internal_elements (::std::move (array_elems)), locus (locus) + {} + + // Copy constructor requires cloning ArrayElems for polymorphism to hold + ArrayExpr (ArrayExpr const &other) + : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), + locus (other.locus) + { + if (other.has_array_elems ()) + { + internal_elements = other.internal_elements->clone_array_elems (); + } + } + + // Destructor - define here if required + + // Overload assignment operator to clone internal_elements + ArrayExpr &operator= (ArrayExpr const &other) + { + ExprWithoutBlock::operator= (other); + inner_attrs = other.inner_attrs; + if (other.has_array_elems ()) + { + internal_elements = other.internal_elements->clone_array_elems (); + } + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ArrayExpr (ArrayExpr &&other) = default; + ArrayExpr &operator= (ArrayExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ArrayExpr *clone_expr_impl () const OVERRIDE + { + return new ArrayExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ArrayExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new ArrayExpr (*this); + } +}; + +// Aka IndexExpr (also applies to slices) +// Apparently a[b] is equivalent to *std::ops::Index::index(&a, b) or +// *std::ops::Index::index_mut(&mut a, b) +// Also apparently deref operations on a will be repeatedly applied to find an +// implementation +class ArrayIndexExpr : public ExprWithoutBlock +{ + /*Expr* array_expr; + Expr* index_expr;*/ + ::std::unique_ptr<Expr> array_expr; + ::std::unique_ptr<Expr> index_expr; + + Location locus; + +public: + /*~ArrayIndexExpr() { + delete index_expr; + delete array_expr; + }*/ + + ::std::string as_string () const; + + ArrayIndexExpr (::std::unique_ptr<Expr> array_expr, + ::std::unique_ptr<Expr> array_index_expr, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), + array_expr (::std::move (array_expr)), + index_expr (::std::move (array_index_expr)), locus (locus) + {} + + // Copy constructor requires special cloning due to unique_ptr + ArrayIndexExpr (ArrayIndexExpr const &other) + : ExprWithoutBlock (other), array_expr (other.array_expr->clone_expr ()), + index_expr (other.index_expr->clone_expr ()), locus (other.locus) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptrs + ArrayIndexExpr &operator= (ArrayIndexExpr const &other) + { + ExprWithoutBlock::operator= (other); + array_expr = other.array_expr->clone_expr (); + index_expr = other.index_expr->clone_expr (); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + ArrayIndexExpr (ArrayIndexExpr &&other) = default; + ArrayIndexExpr &operator= (ArrayIndexExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ArrayIndexExpr *clone_expr_impl () const OVERRIDE + { + return new ArrayIndexExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ArrayIndexExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new ArrayIndexExpr (*this); + } +}; + +// AST representation of a tuple +class TupleExpr : public ExprWithoutBlock +{ + ::std::vector<Attribute> inner_attrs; + + //::std::vector<Expr> tuple_elems; + ::std::vector< ::std::unique_ptr<Expr> > tuple_elems; + // replaces (inlined version of) TupleElements + + Location locus; + +public: + ::std::string as_string () const; + + inline ::std::vector<Attribute> get_inner_attrs () const + { + return inner_attrs; + } + + TupleExpr (::std::vector< ::std::unique_ptr<Expr> > tuple_elements, + ::std::vector<Attribute> inner_attribs, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), + inner_attrs (::std::move (inner_attribs)), + tuple_elems (::std::move (tuple_elements)), locus (locus) + {} + + // copy constructor with vector clone + TupleExpr (TupleExpr const &other) + : ExprWithoutBlock (other), inner_attrs (other.inner_attrs), + locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + tuple_elems.reserve (other.tuple_elems.size ()); + + for (const auto &e : other.tuple_elems) + { + tuple_elems.push_back (e->clone_expr ()); + } + } + + // overloaded assignment operator to vector clone + TupleExpr &operator= (TupleExpr const &other) + { + ExprWithoutBlock::operator= (other); + inner_attrs = other.inner_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + tuple_elems.reserve (other.tuple_elems.size ()); + + for (const auto &e : other.tuple_elems) + { + tuple_elems.push_back (e->clone_expr ()); + } + + return *this; + } + + // move constructors + TupleExpr (TupleExpr &&other) = default; + TupleExpr &operator= (TupleExpr &&other) = default; + + // Note: syntactically, can disambiguate single-element tuple from parens with + // comma, i.e. (0,) rather than (0) + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TupleExpr *clone_expr_impl () const OVERRIDE + { + return new TupleExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual TupleExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new TupleExpr (*this); + } +}; + +// aka TupleIndexingExpr +// AST representation of a tuple indexing expression +class TupleIndexExpr : public ExprWithoutBlock +{ + // Expr* tuple_expr; + ::std::unique_ptr<Expr> tuple_expr; + // TupleIndex is a decimal int literal with no underscores or suffix + TupleIndex tuple_index; + + Location locus; + + // i.e. pair.0 + +public: + /*~TupleIndexExpr() { + delete tuple_expr; + }*/ + + ::std::string as_string () const; + + inline TupleIndex get_tuple_index () const { return tuple_index; } + + TupleIndexExpr (::std::unique_ptr<Expr> tuple_expr, TupleIndex index, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), + tuple_expr (::std::move (tuple_expr)), tuple_index (index), locus (locus) + {} + + // Copy constructor requires a clone for tuple_expr + TupleIndexExpr (TupleIndexExpr const &other) + : ExprWithoutBlock (other), tuple_expr (other.tuple_expr->clone_expr ()), + tuple_index (other.tuple_index), locus (other.locus) + {} + + // Destructor - define here if required + + // Overload assignment operator in order to clone + TupleIndexExpr &operator= (TupleIndexExpr const &other) + { + ExprWithoutBlock::operator= (other); + tuple_expr = other.tuple_expr->clone_expr (); + tuple_index = other.tuple_index; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + TupleIndexExpr (TupleIndexExpr &&other) = default; + TupleIndexExpr &operator= (TupleIndexExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TupleIndexExpr *clone_expr_impl () const OVERRIDE + { + return new TupleIndexExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual TupleIndexExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new TupleIndexExpr (*this); + } +}; + +// Base struct/tuple/union value creator AST node (abstract) +class StructExpr : public ExprWithoutBlock +{ + PathInExpression struct_name; + +protected: + // Protected constructor to allow initialising struct_name + StructExpr (PathInExpression struct_path, + ::std::vector<Attribute> outer_attribs) + : ExprWithoutBlock (::std::move (outer_attribs)), + struct_name (::std::move (struct_path)) + {} + +public: + inline const PathInExpression &get_struct_name () const + { + return struct_name; + } + + virtual ::std::string as_string () const; +}; + +// Actual AST node of the struct creator (with no fields). Not abstract! +class StructExprStruct : public StructExpr +{ + ::std::vector<Attribute> inner_attrs; + + Location locus; + +public: + ::std::string as_string () const; + + inline ::std::vector<Attribute> get_inner_attrs () const + { + return inner_attrs; + } + + // Constructor has to call protected constructor of base class + StructExprStruct (PathInExpression struct_path, + ::std::vector<Attribute> inner_attribs, + ::std::vector<Attribute> outer_attribs, Location locus) + : StructExpr (::std::move (struct_path), ::std::move (outer_attribs)), + inner_attrs (::std::move (inner_attribs)), locus (locus) + {} + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprStruct *clone_expr_impl () const OVERRIDE + { + return new StructExprStruct (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprStruct *clone_expr_without_block_impl () const OVERRIDE + { + return new StructExprStruct (*this); + } +}; + +// AST node representing expression used to fill a struct's fields from another +// struct +struct StructBase +{ +private: + // Expr* base_struct; + ::std::unique_ptr<Expr> base_struct; + + // TODO: should this store location data? + +public: + StructBase (::std::unique_ptr<Expr> base_struct_ptr) + : base_struct (::std::move (base_struct_ptr)) + {} + + // Copy constructor requires clone + StructBase (StructBase const &other) + { + // HACK: gets around base_struct pointer being null (e.g. if no struct base + // exists) + if (other.base_struct != NULL) + { + other.base_struct->clone_expr (); + } + + // DEBUG: + fprintf (stderr, "struct base copy constructor called successfully\n"); + } + + // Destructor + ~StructBase () = default; + + // Overload assignment operator to clone base_struct + StructBase &operator= (StructBase const &other) + { + base_struct = other.base_struct->clone_expr (); + + return *this; + } + + // move constructors + StructBase (StructBase &&other) = default; + StructBase &operator= (StructBase &&other) = default; + + /*~StructBase() { + delete base_struct; + }*/ + + // Returns a null expr-ed StructBase - error state + static StructBase error () { return StructBase (NULL); } + + // Returns whether StructBase is in error state + inline bool is_invalid () const { return base_struct == NULL; } + + ::std::string as_string () const; +}; + +// Base AST node for a single struct expression field (in struct instance +// creation) - abstract +class StructExprField +{ +public: + virtual ~StructExprField () {} + + // Unique pointer custom clone function + ::std::unique_ptr<StructExprField> clone_struct_expr_field () const + { + return ::std::unique_ptr<StructExprField> (clone_struct_expr_field_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // pure virtual clone implementation + virtual StructExprField *clone_struct_expr_field_impl () const = 0; +}; + +// Identifier-only variant of StructExprField AST node +class StructExprFieldIdentifier : public StructExprField +{ + Identifier field_name; + + // TODO: should this store location data? + +public: + StructExprFieldIdentifier (Identifier field_identifier) + : field_name (::std::move (field_identifier)) + {} + + ::std::string as_string () const { return field_name; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this rather than + // base + virtual StructExprFieldIdentifier * + clone_struct_expr_field_impl () const OVERRIDE + { + return new StructExprFieldIdentifier (*this); + } +}; + +// Base AST node for a single struct expression field with an assigned value - +// abstract +class StructExprFieldWithVal : public StructExprField +{ + // Expr* value; + ::std::unique_ptr<Expr> value; + +protected: + StructExprFieldWithVal (::std::unique_ptr<Expr> field_value) + : value (::std::move (field_value)) + {} + + // Copy constructor requires clone + StructExprFieldWithVal (StructExprFieldWithVal const &other) + : value (other.value->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr + StructExprFieldWithVal &operator= (StructExprFieldWithVal const &other) + { + value = other.value->clone_expr (); + + return *this; + } + + // move constructors + StructExprFieldWithVal (StructExprFieldWithVal &&other) = default; + StructExprFieldWithVal &operator= (StructExprFieldWithVal &&other) = default; + +public: + /*~StructExprFieldWithVal() { + delete value; + }*/ + + ::std::string as_string () const; +}; + +// Identifier and value variant of StructExprField AST node +class StructExprFieldIdentifierValue : public StructExprFieldWithVal +{ + Identifier field_name; + + // TODO: should this store location data? + +public: + StructExprFieldIdentifierValue (Identifier field_identifier, + ::std::unique_ptr<Expr> field_value) + : StructExprFieldWithVal (::std::move (field_value)), + field_name (::std::move (field_identifier)) + {} + + // copy constructor, destructor, and overloaded assignment operator should + // carry through + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this rather than + // base + virtual StructExprFieldIdentifierValue * + clone_struct_expr_field_impl () const OVERRIDE + { + return new StructExprFieldIdentifierValue (*this); + } +}; + +// Tuple index and value variant of StructExprField AST node +class StructExprFieldIndexValue : public StructExprFieldWithVal +{ + TupleIndex index; + + // TODO: should this store location data? + +public: + StructExprFieldIndexValue (TupleIndex tuple_index, + ::std::unique_ptr<Expr> field_value) + : StructExprFieldWithVal (::std::move (field_value)), index (tuple_index) + {} + + // copy constructor, destructor, and overloaded assignment operator should + // carry through + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this rather than + // base + virtual StructExprFieldIndexValue * + clone_struct_expr_field_impl () const OVERRIDE + { + return new StructExprFieldIndexValue (*this); + } +}; + +// AST node of a struct creator with fields +class StructExprStructFields : public StructExprStruct +{ + //::std::vector<StructExprField> fields; + ::std::vector< ::std::unique_ptr<StructExprField> > fields; + + // bool has_struct_base; + StructBase struct_base; + +public: + ::std::string as_string () const; + + inline bool has_struct_base () const { return !struct_base.is_invalid (); } + + /*inline ::std::vector< ::std::unique_ptr<StructExprField> > get_fields() + const { return fields; + }*/ + + /*inline StructBase get_struct_base() const { + return has_struct_base ? struct_base : StructBase::error(); + }*/ + + // Constructor for StructExprStructFields when no struct base is used + StructExprStructFields ( + PathInExpression struct_path, + ::std::vector< ::std::unique_ptr<StructExprField> > expr_fields, + Location locus, StructBase base_struct = StructBase::error (), + ::std::vector<Attribute> inner_attribs = ::std::vector<Attribute> (), + ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute> ()) + : StructExprStruct (::std::move (struct_path), ::std::move (inner_attribs), + ::std::move (outer_attribs), locus), + fields (::std::move (expr_fields)), + struct_base (::std::move (base_struct)) + {} + + // copy constructor with vector clone + StructExprStructFields (StructExprStructFields const &other) + : StructExprStruct (other), struct_base (other.struct_base) + { + // DEBUG + fprintf (stderr, + "got past the initialisation list part of copy constructor\n"); + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + fields.reserve (other.fields.size ()); + + // DEBUG + fprintf (stderr, "reserved space in fields\n"); + + for (const auto &e : other.fields) + { + // DEBUG + fprintf (stderr, "about to clone a field\n"); + + fields.push_back (e->clone_struct_expr_field ()); + + // DEBUG + fprintf (stderr, "cloned a field successfully\n"); + } + + // DEBUG + fprintf (stderr, "finished cloning fields\n"); + } + + // overloaded assignment operator with vector clone + StructExprStructFields &operator= (StructExprStructFields const &other) + { + StructExprStruct::operator= (other); + struct_base = other.struct_base; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + fields.reserve (other.fields.size ()); + + for (const auto &e : other.fields) + { + fields.push_back (e->clone_struct_expr_field ()); + } + + return *this; + } + + // move constructors + StructExprStructFields (StructExprStructFields &&other) = default; + StructExprStructFields &operator= (StructExprStructFields &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprStructFields *clone_expr_impl () const OVERRIDE + { + return new StructExprStructFields (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprStructFields * + clone_expr_without_block_impl () const OVERRIDE + { + // DEBUG + fprintf ( + stderr, + "called structexprstructfields clone expr without block impl - about " + "to return new structexprstructfields\n"); + + // DEBUG - test creation of a base from this + fprintf (stderr, "about to try to create and allocate structexprstruct \n"); + StructExprStruct *test_DELETE = new StructExprStruct (*this); + delete test_DELETE; + fprintf (stderr, "managed to create and allocate structexprstruct \n"); + // very weird: can create and allocate structexpstruct but not + // structexprstructfields + + // DEBUG - test creation of a non-returned class from this + fprintf (stderr, "about to try to create and allocate " + "structexprstructfields (but not return)\n"); + StructExprStructFields *test_DELETE2 = new StructExprStructFields (*this); + delete test_DELETE2; + fprintf (stderr, "managed to create and allocate structexprstructfields " + "(if not returned) \n"); + // ok this fails. fair enough. + + return new StructExprStructFields (*this); + } +}; + +// AST node of the functional update struct creator +class StructExprStructBase : public StructExprStruct +{ + StructBase struct_base; + +public: + ::std::string as_string () const; + + /*inline StructBase get_struct_base() const { + return struct_base; + }*/ + + StructExprStructBase (PathInExpression struct_path, StructBase base_struct, + ::std::vector<Attribute> inner_attribs, + ::std::vector<Attribute> outer_attribs, Location locus) + : StructExprStruct (::std::move (struct_path), ::std::move (inner_attribs), + ::std::move (outer_attribs), locus), + struct_base (::std::move (base_struct)) + {} + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprStructBase *clone_expr_impl () const OVERRIDE + { + return new StructExprStructBase (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprStructBase *clone_expr_without_block_impl () const OVERRIDE + { + return new StructExprStructBase (*this); + } +}; + +// AST node of a tuple struct creator +class StructExprTuple : public StructExpr +{ + ::std::vector<Attribute> inner_attrs; + //::std::vector<Expr> exprs; + ::std::vector< ::std::unique_ptr<Expr> > exprs; + + Location locus; + +public: + ::std::string as_string () const; + + inline const ::std::vector<Attribute> &get_inner_attrs () const + { + return inner_attrs; + } + + /*inline ::std::vector< ::std::unique_ptr<Expr> > get_exprs() const { + return exprs; + }*/ + + StructExprTuple (PathInExpression struct_path, + ::std::vector< ::std::unique_ptr<Expr> > tuple_exprs, + ::std::vector<Attribute> inner_attribs, + ::std::vector<Attribute> outer_attribs, Location locus) + : StructExpr (::std::move (struct_path), ::std::move (outer_attribs)), + inner_attrs (::std::move (inner_attribs)), + exprs (::std::move (tuple_exprs)), locus (locus) + {} + + // copy constructor with vector clone + StructExprTuple (StructExprTuple const &other) + : StructExpr (other), inner_attrs (other.inner_attrs), locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + exprs.reserve (other.exprs.size ()); + + for (const auto &e : other.exprs) + { + exprs.push_back (e->clone_expr ()); + } + } + + // overloaded assignment operator with vector clone + StructExprTuple &operator= (StructExprTuple const &other) + { + StructExpr::operator= (other); + inner_attrs = other.inner_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + exprs.reserve (other.exprs.size ()); + + for (const auto &e : other.exprs) + { + exprs.push_back (e->clone_expr ()); + } + + return *this; + } + + // move constructors + StructExprTuple (StructExprTuple &&other) = default; + StructExprTuple &operator= (StructExprTuple &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprTuple *clone_expr_impl () const OVERRIDE + { + return new StructExprTuple (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprTuple *clone_expr_without_block_impl () const OVERRIDE + { + return new StructExprTuple (*this); + } +}; + +// AST node of a "unit" struct creator (no fields and no braces) +class StructExprUnit : public StructExpr +{ + Location locus; + +public: + ::std::string as_string () const + { + return get_struct_name ().as_string (); + // return struct_name.as_string(); + } + + StructExprUnit (PathInExpression struct_path, + ::std::vector<Attribute> outer_attribs, Location locus) + : StructExpr (::std::move (struct_path), ::std::move (outer_attribs)), + locus (locus) + {} + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprUnit *clone_expr_impl () const OVERRIDE + { + return new StructExprUnit (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructExprUnit *clone_expr_without_block_impl () const OVERRIDE + { + return new StructExprUnit (*this); + } +}; + +// aka EnumerationVariantExpr +// Base AST node representing creation of an enum variant instance - abstract +class EnumVariantExpr : public ExprWithoutBlock +{ + PathInExpression enum_variant_path; + +protected: + // Protected constructor for initialising enum_variant_path + EnumVariantExpr (PathInExpression path_to_enum_variant, + ::std::vector<Attribute> outer_attribs) + : ExprWithoutBlock (::std::move (outer_attribs)), + enum_variant_path (::std::move (path_to_enum_variant)) + {} + +public: + // TODO: maybe remove and have string version gotten here directly + inline PathInExpression get_enum_variant_path () const + { + return enum_variant_path; + } +}; + +// Base AST node for a single enum expression field (in enum instance creation) +// - abstract +class EnumExprField +{ +public: + virtual ~EnumExprField () {} + + // Unique pointer custom clone function + ::std::unique_ptr<EnumExprField> clone_enum_expr_field () const + { + return ::std::unique_ptr<EnumExprField> (clone_enum_expr_field_impl ()); + } + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // Clone function implementation as pure virtual method + virtual EnumExprField *clone_enum_expr_field_impl () const = 0; +}; + +// Identifier-only variant of EnumExprField AST node +class EnumExprFieldIdentifier : public EnumExprField +{ + Identifier field_name; + + // TODO: should this store location data? + +public: + EnumExprFieldIdentifier (Identifier field_identifier) + : field_name (::std::move (field_identifier)) + {} + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual EnumExprFieldIdentifier *clone_enum_expr_field_impl () const OVERRIDE + { + return new EnumExprFieldIdentifier (*this); + } +}; + +// Base AST node for a single enum expression field with an assigned value - +// abstract +class EnumExprFieldWithVal : public EnumExprField +{ + // Expr* value; + ::std::unique_ptr<Expr> value; + + // TODO: should this store location data? + +protected: + EnumExprFieldWithVal (::std::unique_ptr<Expr> field_value) + : value (::std::move (field_value)) + {} + + // Copy constructor must clone unique_ptr value + EnumExprFieldWithVal (EnumExprFieldWithVal const &other) + : value (other.value->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone + EnumExprFieldWithVal &operator= (EnumExprFieldWithVal const &other) + { + value = other.value->clone_expr (); + + return *this; + } + + // move constructors + EnumExprFieldWithVal (EnumExprFieldWithVal &&other) = default; + EnumExprFieldWithVal &operator= (EnumExprFieldWithVal &&other) = default; +}; + +// Identifier and value variant of EnumExprField AST node +class EnumExprFieldIdentifierValue : public EnumExprFieldWithVal +{ + Identifier field_name; + + // TODO: should this store location data? + +public: + EnumExprFieldIdentifierValue (Identifier field_name, + ::std::unique_ptr<Expr> field_value) + : EnumExprFieldWithVal (::std::move (field_value)), + field_name (::std::move (field_name)) + {} + + // copy constructor, destructor, and assignment operator should not need + // defining + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual EnumExprFieldIdentifierValue * + clone_enum_expr_field_impl () const OVERRIDE + { + return new EnumExprFieldIdentifierValue (*this); + } +}; + +// Tuple index and value variant of EnumExprField AST node +class EnumExprFieldIndexValue : public EnumExprFieldWithVal +{ + TupleIndex index; + // TODO: implement "with val" as a template with EnumExprField as type param? + + // TODO: should this store location data? + +public: + EnumExprFieldIndexValue (TupleIndex field_index, + ::std::unique_ptr<Expr> field_value) + : EnumExprFieldWithVal (::std::move (field_value)), index (field_index) + {} + + // copy constructor, destructor, and assignment operator should not need + // defining + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual EnumExprFieldIndexValue *clone_enum_expr_field_impl () const OVERRIDE + { + return new EnumExprFieldIndexValue (*this); + } +}; + +// Struct-like syntax enum variant instance creation AST node +class EnumExprStruct : public EnumVariantExpr +{ + //::std::vector<EnumExprField> fields; + ::std::vector< ::std::unique_ptr<EnumExprField> > fields; + + Location locus; + +public: + ::std::string as_string () const; + + /*inline ::std::vector< ::std::unique_ptr<EnumExprField> > get_fields() const + { return fields; + }*/ + + EnumExprStruct ( + PathInExpression enum_variant_path, + ::std::vector< ::std::unique_ptr<EnumExprField> > variant_fields, + ::std::vector<Attribute> outer_attribs, Location locus) + : EnumVariantExpr (::std::move (enum_variant_path), + ::std::move (outer_attribs)), + fields (::std::move (variant_fields)), locus (locus) + {} + + // copy constructor with vector clone + EnumExprStruct (EnumExprStruct const &other) + : EnumVariantExpr (other), locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + fields.reserve (other.fields.size ()); + + for (const auto &e : other.fields) + { + fields.push_back (e->clone_enum_expr_field ()); + } + } + + // overloaded assignment operator with vector clone + EnumExprStruct &operator= (EnumExprStruct const &other) + { + EnumVariantExpr::operator= (other); + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + fields.reserve (other.fields.size ()); + + for (const auto &e : other.fields) + { + fields.push_back (e->clone_enum_expr_field ()); + } + + return *this; + } + + // move constructors + EnumExprStruct (EnumExprStruct &&other) = default; + EnumExprStruct &operator= (EnumExprStruct &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual EnumExprStruct *clone_expr_impl () const OVERRIDE + { + return new EnumExprStruct (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual EnumExprStruct *clone_expr_without_block_impl () const OVERRIDE + { + return new EnumExprStruct (*this); + } +}; + +// Tuple-like syntax enum variant instance creation AST node +class EnumExprTuple : public EnumVariantExpr +{ + //::std::vector<Expr> values; + ::std::vector< ::std::unique_ptr<Expr> > values; + + Location locus; + +public: + ::std::string as_string () const; + + /*inline ::std::vector< ::std::unique_ptr<Expr> > get_values() const { + return values; + }*/ + + EnumExprTuple (PathInExpression enum_variant_path, + ::std::vector< ::std::unique_ptr<Expr> > variant_values, + ::std::vector<Attribute> outer_attribs, Location locus) + : EnumVariantExpr (::std::move (enum_variant_path), + ::std::move (outer_attribs)), + values (::std::move (variant_values)), locus (locus) + {} + + // copy constructor with vector clone + EnumExprTuple (EnumExprTuple const &other) + : EnumVariantExpr (other), locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + values.reserve (other.values.size ()); + + for (const auto &e : other.values) + { + values.push_back (e->clone_expr ()); + } + } + + // overloaded assignment operator with vector clone + EnumExprTuple &operator= (EnumExprTuple const &other) + { + EnumVariantExpr::operator= (other); + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + values.reserve (other.values.size ()); + + for (const auto &e : other.values) + { + values.push_back (e->clone_expr ()); + } + + return *this; + } + + // move constructors + EnumExprTuple (EnumExprTuple &&other) = default; + EnumExprTuple &operator= (EnumExprTuple &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual EnumExprTuple *clone_expr_impl () const OVERRIDE + { + return new EnumExprTuple (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual EnumExprTuple *clone_expr_without_block_impl () const OVERRIDE + { + return new EnumExprTuple (*this); + } +}; + +// No-field enum variant instance creation AST node +class EnumExprFieldless : public EnumVariantExpr +{ + Location locus; + +public: + ::std::string as_string () const + { + // return enum_variant_path.as_string(); + return get_enum_variant_path ().as_string (); + } + + EnumExprFieldless (PathInExpression enum_variant_path, + ::std::vector<Attribute> outer_attribs, Location locus) + : EnumVariantExpr (::std::move (enum_variant_path), + ::std::move (outer_attribs)), + locus (locus) + {} + + // copy constructor, destructor, and assignment operator should not need + // defining + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual EnumExprFieldless *clone_expr_impl () const OVERRIDE + { + return new EnumExprFieldless (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual EnumExprFieldless *clone_expr_without_block_impl () const OVERRIDE + { + return new EnumExprFieldless (*this); + } +}; + +// Function call expression AST node +class CallExpr : public ExprWithoutBlock +{ + // Expr* function; + ::std::unique_ptr<Expr> function; + //::std::vector<Expr> params; // inlined form of CallParams + ::std::vector< ::std::unique_ptr<Expr> > params; + + Location locus; + +public: + /*~CallExpr() { + delete function; + }*/ + + ::std::string as_string () const; + + /*inline ::std::vector< ::std::unique_ptr<Expr> > get_params() const { + return params; + }*/ + + CallExpr (::std::unique_ptr<Expr> function_expr, + ::std::vector< ::std::unique_ptr<Expr> > function_params, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), + function (::std::move (function_expr)), + params (::std::move (function_params)), locus (locus) + {} + + // copy constructor requires clone + CallExpr (CallExpr const &other) + : ExprWithoutBlock (other), function (other.function->clone_expr ()), + locus (other.locus) + /*, params(other.params),*/ { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + params.reserve (other.params.size ()); + + for (const auto &e : other.params) + { + params.push_back (e->clone_expr ()); + } + } + + // Destructor - define here if required + + // Overload assignment operator to clone + CallExpr &operator= (CallExpr const &other) + { + ExprWithoutBlock::operator= (other); + function = other.function->clone_expr (); + locus = other.locus; + // params = other.params; + // outer_attrs = other.outer_attrs; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + params.reserve (other.params.size ()); + + for (const auto &e : other.params) + { + params.push_back (e->clone_expr ()); + } + + return *this; + } + + // move constructors + CallExpr (CallExpr &&other) = default; + CallExpr &operator= (CallExpr &&other) = default; + + // Returns whether function call has parameters. + inline bool has_params () const { return !params.empty (); } + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual CallExpr *clone_expr_impl () const OVERRIDE + { + return new CallExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual CallExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new CallExpr (*this); + } +}; + +// Method call expression AST node +class MethodCallExpr : public ExprWithoutBlock +{ + // Expr* receiver; + ::std::unique_ptr<Expr> receiver; + PathExprSegment method_name; + //::std::vector<Expr> params; // inlined form of CallParams + ::std::vector< ::std::unique_ptr<Expr> > params; + + Location locus; + +public: + /*~MethodCallExpr() { + delete receiver; + }*/ + + ::std::string as_string () const; + + /*inline ::std::vector< ::std::unique_ptr<Expr> > get_params() const { + return params; + }*/ + + MethodCallExpr (::std::unique_ptr<Expr> call_receiver, + PathExprSegment method_path, + ::std::vector< ::std::unique_ptr<Expr> > method_params, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), + receiver (::std::move (call_receiver)), + method_name (::std::move (method_path)), + params (::std::move (method_params)), locus (locus) + {} + + // copy constructor required due to cloning + MethodCallExpr (MethodCallExpr const &other) + : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()), + method_name (other.method_name), locus (other.locus) + /*, params(other.params),*/ { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + params.reserve (other.params.size ()); + + for (const auto &e : other.params) + { + params.push_back (e->clone_expr ()); + } + } + + // Destructor - define here if required + + // Overload assignment operator to clone receiver object + MethodCallExpr &operator= (MethodCallExpr const &other) + { + ExprWithoutBlock::operator= (other); + receiver = other.receiver->clone_expr (); + method_name = other.method_name; + locus = other.locus; + // params = other.params; + // outer_attrs = other.outer_attrs; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + params.reserve (other.params.size ()); + + for (const auto &e : other.params) + { + params.push_back (e->clone_expr ()); + } + + return *this; + } + + // move constructors + MethodCallExpr (MethodCallExpr &&other) = default; + MethodCallExpr &operator= (MethodCallExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MethodCallExpr *clone_expr_impl () const OVERRIDE + { + return new MethodCallExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual MethodCallExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new MethodCallExpr (*this); + } +}; + +// aka FieldExpression +// Struct or union field access expression AST node +class FieldAccessExpr : public ExprWithoutBlock +{ + // Expr* receiver; + ::std::unique_ptr<Expr> receiver; + Identifier field; + + Location locus; + +public: + /*~FieldAccessExpr() { + delete receiver; + }*/ + + ::std::string as_string () const; + + FieldAccessExpr (::std::unique_ptr<Expr> field_access_receiver, + Identifier field_name, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), + receiver (::std::move (field_access_receiver)), + field (::std::move (field_name)), locus (locus) + {} + + // Copy constructor required due to unique_ptr cloning + FieldAccessExpr (FieldAccessExpr const &other) + : ExprWithoutBlock (other), receiver (other.receiver->clone_expr ()), + field (other.field), locus (other.locus) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr + FieldAccessExpr &operator= (FieldAccessExpr const &other) + { + ExprWithoutBlock::operator= (other); + receiver = other.receiver->clone_expr (); + field = other.field; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + FieldAccessExpr (FieldAccessExpr &&other) = default; + FieldAccessExpr &operator= (FieldAccessExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual FieldAccessExpr *clone_expr_impl () const OVERRIDE + { + return new FieldAccessExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual FieldAccessExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new FieldAccessExpr (*this); + } +}; + +// Closure parameter data structure +struct ClosureParam +{ +private: + // Pattern pattern; + ::std::unique_ptr<Pattern> pattern; + + // bool has_type_given; + // Type type; + ::std::unique_ptr<Type> type; + + // TODO: should this store location data? + +public: + // Returns whether the type of the parameter has been given. + inline bool has_type_given () const { return type != NULL; } + + // Constructor for closure parameter + ClosureParam (::std::unique_ptr<Pattern> param_pattern, + ::std::unique_ptr<Type> param_type = NULL) + : pattern (::std::move (param_pattern)), type (::std::move (param_type)) + {} + + // Copy constructor required due to cloning as a result of unique_ptrs + ClosureParam (ClosureParam const &other) + : pattern (other.pattern->clone_pattern ()) + { + // guard to protect from null pointer dereference + if (other.type != NULL) + { + type = other.type->clone_type (); + } + } + + ~ClosureParam () = default; + + // Assignment operator must be overloaded to clone as well + ClosureParam &operator= (ClosureParam const &other) + { + pattern = other.pattern->clone_pattern (); + type = other.type->clone_type (); + + return *this; + } + + // move constructors + ClosureParam (ClosureParam &&other) = default; + ClosureParam &operator= (ClosureParam &&other) = default; + + // Returns whether closure parameter is in an error state. + inline bool is_error () const { return pattern == NULL; } + + // Creates an error state closure parameter. + static ClosureParam create_error () { return ClosureParam (NULL); } + + ::std::string as_string () const; +}; + +// Base closure definition expression AST node - abstract +class ClosureExpr : public ExprWithoutBlock +{ + bool has_move; + ::std::vector<ClosureParam> params; // may be empty + // also note a double pipe "||" can be used for empty params - does not need a + // space + + Location locus; + +protected: + ClosureExpr (::std::vector<ClosureParam> closure_params, bool has_move, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (::std::move (outer_attribs)), has_move (has_move), + params (::std::move (closure_params)), locus (locus) + {} + + // Copy constructor, destructor, and assignment operator override should not + // be needed +public: + virtual ::std::string as_string () const; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } +}; + +// Represents a non-type-specified closure expression AST node +class ClosureExprInner : public ClosureExpr +{ + // Expr* closure_inner; + ::std::unique_ptr<Expr> closure_inner; + +public: + /*~ClosureExprInner() { + delete closure_inner; + }*/ + + ::std::string as_string () const; + + // Constructor for a ClosureExprInner + ClosureExprInner (::std::unique_ptr<Expr> closure_inner_expr, + ::std::vector<ClosureParam> closure_params, Location locus, + bool is_move = false, + ::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : ClosureExpr (::std::move (closure_params), is_move, + ::std::move (outer_attribs), locus), + closure_inner (::std::move (closure_inner_expr)) + {} + + // Copy constructor must be defined to allow copying via cloning of unique_ptr + ClosureExprInner (ClosureExprInner const &other) + : ClosureExpr (other), closure_inner (other.closure_inner->clone_expr ()) + {} + // TODO: ensure that this actually constructs properly + + // Destructor - define here if required + + // Overload assignment operator to clone closure_inner + ClosureExprInner &operator= (ClosureExprInner const &other) + { + ClosureExpr::operator= (other); + closure_inner = other.closure_inner->clone_expr (); + // params = other.params; + // has_move = other.has_move; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ClosureExprInner (ClosureExprInner &&other) = default; + ClosureExprInner &operator= (ClosureExprInner &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ClosureExprInner *clone_expr_impl () const OVERRIDE + { + return new ClosureExprInner (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ClosureExprInner *clone_expr_without_block_impl () const OVERRIDE + { + return new ClosureExprInner (*this); + } +}; + +// Forward decl BlockExpr for ClosureExprInnerTyped +// class BlockExpr; + +// A block AST node +class BlockExpr : public ExprWithBlock +{ + ::std::vector<Attribute> inner_attrs; + + /*bool has_statements; + Statements statements;*/ + + // bool has_statements; + ::std::vector< ::std::unique_ptr<Stmt> > statements; + // bool has_expr; + ::std::unique_ptr<ExprWithoutBlock> expr; // inlined from Statements + + Location locus; + +public: + ::std::string as_string () const; + + // Returns whether the block contains statements. + inline bool has_statements () const { return !statements.empty (); } + + // Returns whether the block contains an expression + inline bool has_expr () const { return expr != NULL; } + + BlockExpr (::std::vector< ::std::unique_ptr<Stmt> > block_statements, + ::std::unique_ptr<ExprWithoutBlock> block_expr, + ::std::vector<Attribute> inner_attribs, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithBlock (::std::move (outer_attribs)), + inner_attrs (::std::move (inner_attribs)), + statements (::std::move (block_statements)), + expr (::std::move (block_expr)), locus (locus) + {} + + // Copy constructor with clone + BlockExpr (BlockExpr const &other) + : ExprWithBlock (other), /*statements(other.statements),*/ + inner_attrs (other.inner_attrs), locus (other.locus) + { + // guard to protect from null pointer dereference + if (other.expr != NULL) + { + expr = other.expr->clone_expr_without_block (); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + statements.reserve (other.statements.size ()); + + for (const auto &e : other.statements) + { + statements.push_back (e->clone_stmt ()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone pointer + BlockExpr &operator= (BlockExpr const &other) + { + ExprWithBlock::operator= (other); + // statements = other.statements; + expr = other.expr->clone_expr_without_block (); + inner_attrs = other.inner_attrs; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + statements.reserve (other.statements.size ()); + + for (const auto &e : other.statements) + { + statements.push_back (e->clone_stmt ()); + } + + return *this; + } + + // move constructors + BlockExpr (BlockExpr &&other) = default; + BlockExpr &operator= (BlockExpr &&other) = default; + + // Unique pointer custom clone function + ::std::unique_ptr<BlockExpr> clone_block_expr () const + { + return ::std::unique_ptr<BlockExpr> (clone_block_expr_impl ()); + } + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual BlockExpr *clone_expr_impl () const OVERRIDE + { + return new BlockExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual BlockExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new BlockExpr (*this); + } + + /* This is the base method as not an abstract class - not virtual but could be + * in future if required. */ + /*virtual*/ BlockExpr *clone_block_expr_impl () const + { + return new BlockExpr (*this); + } +}; + +// Represents a type-specified closure expression AST node +class ClosureExprInnerTyped : public ClosureExpr +{ + // Type return_type; + ::std::unique_ptr<Type> return_type; + // BlockExpr* expr; + ::std::unique_ptr<BlockExpr> + expr; // only used because may be polymorphic in future + +public: + /*~ClosureExprInnerTyped() { + delete expr; + }*/ + + ::std::string as_string () const; + + // Constructor potentially with a move + ClosureExprInnerTyped (::std::unique_ptr<Type> closure_return_type, + ::std::unique_ptr<BlockExpr> closure_expr, + ::std::vector<ClosureParam> closure_params, + Location locus, bool is_move = false, + ::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : ClosureExpr (::std::move (closure_params), is_move, + ::std::move (outer_attribs), locus), + return_type (::std::move (closure_return_type)), + expr (::std::move (closure_expr)) + {} + + // Copy constructor requires cloning + ClosureExprInnerTyped (ClosureExprInnerTyped const &other) + : ClosureExpr (other), return_type (other.return_type->clone_type ()), + expr (other.expr->clone_block_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptrs + ClosureExprInnerTyped &operator= (ClosureExprInnerTyped const &other) + { + ClosureExpr::operator= (other); + return_type = other.return_type->clone_type (); + expr = other.expr->clone_block_expr (); + // params = other.params; + // has_move = other.has_move; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ClosureExprInnerTyped (ClosureExprInnerTyped &&other) = default; + ClosureExprInnerTyped &operator= (ClosureExprInnerTyped &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ClosureExprInnerTyped *clone_expr_impl () const OVERRIDE + { + return new ClosureExprInnerTyped (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ClosureExprInnerTyped *clone_expr_without_block_impl () const OVERRIDE + { + return new ClosureExprInnerTyped (*this); + } +}; + +// AST node representing continue expression within loops +class ContinueExpr : public ExprWithoutBlock +{ + // bool has_label; + Lifetime label; + + Location locus; + +public: + ::std::string as_string () const; + + // Returns true if the continue expr has a label. + inline bool has_label () const { return !label.is_error (); } + + // Constructor for a ContinueExpr with a label. + ContinueExpr (Location locus, Lifetime label = Lifetime::error (), + ::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : ExprWithoutBlock (::std::move (outer_attribs)), + label (::std::move (label)), locus (locus) + {} + + // copy constructor, destructor, and assignment operator should not need + // defining + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ContinueExpr *clone_expr_impl () const OVERRIDE + { + return new ContinueExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ContinueExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new ContinueExpr (*this); + } +}; +// TODO: merge "break" and "continue"? Or even merge in "return"? + +// AST node representing break expression within loops +class BreakExpr : public ExprWithoutBlock +{ + // bool has_label; + Lifetime label; + + // bool has_break_expr; + // Expr* break_expr; // may be uninitialised + ::std::unique_ptr<Expr> break_expr; + + Location locus; + +public: + /*~BreakExpr() { + if (has_break_expr) { + delete break_expr; + } + }*/ + + ::std::string as_string () const; + + // Returns whether the break expression has a label or not. + inline bool has_label () const { return !label.is_error (); } + + // Returns whether the break expression has an expression used in the break or + // not. + inline bool has_break_expr () const { return break_expr != NULL; } + + // Constructor for a break expression + BreakExpr (Location locus, Lifetime break_label = Lifetime::error (), + ::std::unique_ptr<Expr> expr_in_break = NULL, + ::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : ExprWithoutBlock (::std::move (outer_attribs)), + label (::std::move (break_label)), + break_expr (::std::move (expr_in_break)), locus (locus) + {} + + // Copy constructor defined to use clone for unique pointer + BreakExpr (BreakExpr const &other) + : ExprWithoutBlock (other), label (other.label), locus (other.locus) + { + // guard to protect from null pointer dereference + if (other.break_expr != NULL) + { + break_expr = other.break_expr->clone_expr (); + } + } + + // Destructor - define here if required + + // Overload assignment operator to clone unique pointer + BreakExpr &operator= (BreakExpr const &other) + { + ExprWithoutBlock::operator= (other); + label = other.label; + break_expr = other.break_expr->clone_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + BreakExpr (BreakExpr &&other) = default; + BreakExpr &operator= (BreakExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual BreakExpr *clone_expr_impl () const OVERRIDE + { + return new BreakExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual BreakExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new BreakExpr (*this); + } +}; + +// Base range expression AST node object - abstract +class RangeExpr : public ExprWithoutBlock +{ + Location locus; + +protected: + // outer attributes not allowed before range expressions + RangeExpr (Location locus) + : ExprWithoutBlock (::std::vector<Attribute> ()), locus (locus) + {} + +public: + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } +}; + +// Range from (inclusive) and to (exclusive) expression AST node object +// aka RangeExpr; constructs a std::ops::Range object +class RangeFromToExpr : public RangeExpr +{ + /*Expr* from; + Expr* to;*/ + ::std::unique_ptr<Expr> from; + ::std::unique_ptr<Expr> to; + +public: + /*~RangeFromToExpr() { + delete from; + delete to; + }*/ + + ::std::string as_string () const; + + RangeFromToExpr (::std::unique_ptr<Expr> range_from, + ::std::unique_ptr<Expr> range_to, Location locus) + : RangeExpr (locus), from (::std::move (range_from)), + to (::std::move (range_to)) + {} + + // Copy constructor with cloning + RangeFromToExpr (RangeFromToExpr const &other) + : RangeExpr (other), from (other.from->clone_expr ()), + to (other.to->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique pointers + RangeFromToExpr &operator= (RangeFromToExpr const &other) + { + RangeExpr::operator= (other); + from = other.from->clone_expr (); + to = other.to->clone_expr (); + + return *this; + } + + // move constructors + RangeFromToExpr (RangeFromToExpr &&other) = default; + RangeFromToExpr &operator= (RangeFromToExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeFromToExpr *clone_expr_impl () const OVERRIDE + { + return new RangeFromToExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeFromToExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new RangeFromToExpr (*this); + } +}; + +// Range from (inclusive) expression AST node object +// constructs a std::ops::RangeFrom object +class RangeFromExpr : public RangeExpr +{ + // Expr* from; + ::std::unique_ptr<Expr> from; + +public: + /*~RangeFromExpr() { + delete from; + }*/ + + ::std::string as_string () const; + + RangeFromExpr (::std::unique_ptr<Expr> range_from, Location locus) + : RangeExpr (locus), from (::std::move (range_from)) + {} + + // Copy constructor with clone + RangeFromExpr (RangeFromExpr const &other) + : RangeExpr (other), from (other.from->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr + RangeFromExpr &operator= (RangeFromExpr const &other) + { + RangeExpr::operator= (other); + from = other.from->clone_expr (); + + return *this; + } + + // move constructors + RangeFromExpr (RangeFromExpr &&other) = default; + RangeFromExpr &operator= (RangeFromExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeFromExpr *clone_expr_impl () const OVERRIDE + { + return new RangeFromExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeFromExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new RangeFromExpr (*this); + } +}; + +// Range to (exclusive) expression AST node object +// constructs a std::ops::RangeTo object +class RangeToExpr : public RangeExpr +{ + // Expr* to; + ::std::unique_ptr<Expr> to; + +public: + /*~RangeToExpr() { + delete to; + }*/ + + ::std::string as_string () const; + + // outer attributes not allowed + RangeToExpr (::std::unique_ptr<Expr> range_to, Location locus) + : RangeExpr (locus), to (::std::move (range_to)) + {} + + // Copy constructor with clone + RangeToExpr (RangeToExpr const &other) + : RangeExpr (other), to (other.to->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone unique_ptr + RangeToExpr &operator= (RangeToExpr const &other) + { + RangeExpr::operator= (other); + to = other.to->clone_expr (); + + return *this; + } + + // move constructors + RangeToExpr (RangeToExpr &&other) = default; + RangeToExpr &operator= (RangeToExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeToExpr *clone_expr_impl () const OVERRIDE + { + return new RangeToExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeToExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new RangeToExpr (*this); + } +}; + +// Full range expression AST node object +// constructs a std::ops::RangeFull object +class RangeFullExpr : public RangeExpr +{ +public: + ::std::string as_string () const; + + RangeFullExpr (Location locus) : RangeExpr (locus) {} + // outer attributes not allowed + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeFullExpr *clone_expr_impl () const OVERRIDE + { + return new RangeFullExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeFullExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new RangeFullExpr (*this); + } +}; + +// Range from (inclusive) and to (inclusive) expression AST node object +// aka RangeInclusiveExpr; constructs a std::ops::RangeInclusive object +class RangeFromToInclExpr : public RangeExpr +{ + /*Expr* from; + Expr* to;*/ + ::std::unique_ptr<Expr> from; + ::std::unique_ptr<Expr> to; + +public: + /*~RangeFromToInclExpr() { + delete from; + delete to; + }*/ + + ::std::string as_string () const; + + RangeFromToInclExpr (::std::unique_ptr<Expr> range_from, + ::std::unique_ptr<Expr> range_to, Location locus) + : RangeExpr (locus), from (::std::move (range_from)), + to (::std::move (range_to)) + {} + // outer attributes not allowed + + // Copy constructor with clone + RangeFromToInclExpr (RangeFromToInclExpr const &other) + : RangeExpr (other), from (other.from->clone_expr ()), + to (other.to->clone_expr ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to use clone + RangeFromToInclExpr &operator= (RangeFromToInclExpr const &other) + { + RangeExpr::operator= (other); + from = other.from->clone_expr (); + to = other.to->clone_expr (); + + return *this; + } + + // move constructors + RangeFromToInclExpr (RangeFromToInclExpr &&other) = default; + RangeFromToInclExpr &operator= (RangeFromToInclExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeFromToInclExpr *clone_expr_impl () const OVERRIDE + { + return new RangeFromToInclExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeFromToInclExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new RangeFromToInclExpr (*this); + } +}; + +// Range to (inclusive) expression AST node object +// aka RangeToInclusiveExpr; constructs a std::ops::RangeToInclusive object +class RangeToInclExpr : public RangeExpr +{ + // Expr* to; + ::std::unique_ptr<Expr> to; + +public: + /*~RangeToInclExpr() { + delete to; + }*/ + + ::std::string as_string () const; + + RangeToInclExpr (::std::unique_ptr<Expr> range_to, Location locus) + : RangeExpr (locus), to (::std::move (range_to)) + {} + // outer attributes not allowed + + // Copy constructor with clone + RangeToInclExpr (RangeToInclExpr const &other) + : RangeExpr (other), to (other.to->clone_expr ()) + {} + + // Define destructor here if required + + // Overload assignment operator to clone pointer + RangeToInclExpr &operator= (RangeToInclExpr const &other) + { + RangeExpr::operator= (other); + to = other.to->clone_expr (); + + return *this; + } + + // move constructors + RangeToInclExpr (RangeToInclExpr &&other) = default; + RangeToInclExpr &operator= (RangeToInclExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeToInclExpr *clone_expr_impl () const OVERRIDE + { + return new RangeToInclExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangeToInclExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new RangeToInclExpr (*this); + } +}; + +// Return expression AST node representation +class ReturnExpr : public ExprWithoutBlock +{ + // bool has_return_expr; + // Expr* return_expr; + ::std::unique_ptr<Expr> return_expr; + + Location locus; + +public: + /*~ReturnExpr() { + if (has_return_expr) { + delete return_expr; + } + }*/ + + ::std::string as_string () const; + + // Returns whether the object has an expression returned (i.e. not void return + // type). + inline bool has_return_expr () const { return return_expr != NULL; } + + // Constructor for ReturnExpr. + ReturnExpr (Location locus, ::std::unique_ptr<Expr> returned_expr = NULL, + ::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : ExprWithoutBlock (::std::move (outer_attribs)), + return_expr (::std::move (returned_expr)), locus (locus) + {} + + // Copy constructor with clone + ReturnExpr (ReturnExpr const &other) + : ExprWithoutBlock (other), locus (other.locus) + { + // guard to protect from null pointer dereference + if (other.return_expr != NULL) + { + return_expr = other.return_expr->clone_expr (); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone return_expr pointer + ReturnExpr &operator= (ReturnExpr const &other) + { + ExprWithoutBlock::operator= (other); + return_expr = other.return_expr->clone_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + ReturnExpr (ReturnExpr &&other) = default; + ReturnExpr &operator= (ReturnExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ReturnExpr *clone_expr_impl () const OVERRIDE + { + return new ReturnExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ReturnExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new ReturnExpr (*this); + } +}; + +// Forward decl - defined in rust-macro.h +class MacroInvocation; +/*class MacroInvocation : public ExprWithoutBlock { + public: + ::std::string as_string() const; +};*/ + +// An unsafe block AST node +class UnsafeBlockExpr : public ExprWithBlock +{ + // Or just have it extend BlockExpr + // BlockExpr* expr; + ::std::unique_ptr<BlockExpr> expr; + + Location locus; + +public: + /*~UnsafeBlockExpr() { + delete expr; + }*/ + + ::std::string as_string () const; + + UnsafeBlockExpr (::std::unique_ptr<BlockExpr> block_expr, + ::std::vector<Attribute> outer_attribs, Location locus) + : ExprWithBlock (::std::move (outer_attribs)), + expr (::std::move (block_expr)), locus (locus) + {} + + // Copy constructor with clone + UnsafeBlockExpr (UnsafeBlockExpr const &other) + : ExprWithBlock (other), expr (other.expr->clone_block_expr ()), + locus (other.locus) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + UnsafeBlockExpr &operator= (UnsafeBlockExpr const &other) + { + ExprWithBlock::operator= (other); + expr = other.expr->clone_block_expr (); + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + UnsafeBlockExpr (UnsafeBlockExpr &&other) = default; + UnsafeBlockExpr &operator= (UnsafeBlockExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual UnsafeBlockExpr *clone_expr_impl () const OVERRIDE + { + return new UnsafeBlockExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual UnsafeBlockExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new UnsafeBlockExpr (*this); + } +}; + +// Loop label expression AST node used with break and continue expressions +// TODO: inline? +class LoopLabel /*: public Node*/ +{ + Lifetime label; // or type LIFETIME_OR_LABEL + + Location locus; + +public: + ::std::string as_string () const; + + LoopLabel (Lifetime loop_label, Location locus = Location ()) + : label (::std::move (loop_label)), locus (locus) + {} + + // Returns whether the LoopLabel is in an error state. + inline bool is_error () const { return label.is_error (); } + + // Creates an error state LoopLabel. + static LoopLabel error () { return LoopLabel (Lifetime::error ()); } + + Location get_locus () const { return locus; } +}; + +// Base loop expression AST node - aka LoopExpr +class BaseLoopExpr : public ExprWithBlock +{ +protected: + // protected to allow subclasses better use of them + // bool has_loop_label; + LoopLabel loop_label; + + // BlockExpr* loop_block; + ::std::unique_ptr<BlockExpr> loop_block; + +private: + Location locus; + +protected: + // Constructor for BaseLoopExpr + BaseLoopExpr (::std::unique_ptr<BlockExpr> loop_block, Location locus, + LoopLabel loop_label = LoopLabel::error (), + ::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : ExprWithBlock (::std::move (outer_attribs)), + loop_label (::std::move (loop_label)), + loop_block (::std::move (loop_block)), locus (locus) + {} + + // Copy constructor for BaseLoopExpr with clone + BaseLoopExpr (BaseLoopExpr const &other) + : ExprWithBlock (other), loop_label (other.loop_label), + loop_block (other.loop_block->clone_block_expr ()), locus (other.locus) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + BaseLoopExpr &operator= (BaseLoopExpr const &other) + { + ExprWithBlock::operator= (other); + loop_block = other.loop_block->clone_block_expr (); + loop_label = other.loop_label; + locus = other.locus; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + BaseLoopExpr (BaseLoopExpr &&other) = default; + BaseLoopExpr &operator= (BaseLoopExpr &&other) = default; + +public: + /*~BaseLoopExpr() { + delete loop_block; + }*/ + + inline bool has_loop_label () const { return !loop_label.is_error (); } + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } +}; + +// 'Loop' expression (i.e. the infinite loop) AST node +class LoopExpr : public BaseLoopExpr +{ +public: + ::std::string as_string () const; + + // Constructor for LoopExpr + LoopExpr (::std::unique_ptr<BlockExpr> loop_block, Location locus, + LoopLabel loop_label = LoopLabel::error (), + ::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : BaseLoopExpr (::std::move (loop_block), locus, ::std::move (loop_label), + ::std::move (outer_attribs)) + {} + + // copy constructor, destructor, and assignment operator should not need + // modification + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual LoopExpr *clone_expr_impl () const OVERRIDE + { + return new LoopExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual LoopExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new LoopExpr (*this); + } +}; + +// While loop expression AST node (predicate loop) +class WhileLoopExpr : public BaseLoopExpr +{ + // Expr* condition; + ::std::unique_ptr<Expr> condition; + +public: + /*~WhileLoopExpr() { + delete condition; + }*/ + + ::std::string as_string () const; + + // Constructor for while loop with loop label + WhileLoopExpr (::std::unique_ptr<Expr> loop_condition, + ::std::unique_ptr<BlockExpr> loop_block, Location locus, + LoopLabel loop_label = LoopLabel::error (), + ::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : BaseLoopExpr (::std::move (loop_block), locus, ::std::move (loop_label), + ::std::move (outer_attribs)), + condition (::std::move (loop_condition)) + {} + + // Copy constructor with clone + WhileLoopExpr (WhileLoopExpr const &other) + : BaseLoopExpr (other), condition (other.condition->clone_expr ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + WhileLoopExpr &operator= (WhileLoopExpr const &other) + { + BaseLoopExpr::operator= (other); + condition = other.condition->clone_expr (); + // loop_block = other.loop_block->clone_block_expr(); + // loop_label = other.loop_label; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + WhileLoopExpr (WhileLoopExpr &&other) = default; + WhileLoopExpr &operator= (WhileLoopExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual WhileLoopExpr *clone_expr_impl () const OVERRIDE + { + return new WhileLoopExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual WhileLoopExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new WhileLoopExpr (*this); + } +}; + +// Forward decl MatchArmPatterns +// struct MatchArmPatterns; + +// While let loop expression AST node (predicate pattern loop) +class WhileLetLoopExpr : public BaseLoopExpr +{ + // MatchArmPatterns patterns; + ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns; // inlined + // Expr* condition; + ::std::unique_ptr<Expr> condition; + +public: + /*~WhileLetLoopExpr() { + delete condition; + }*/ + + ::std::string as_string () const; + + // Constructor with a loop label + WhileLetLoopExpr ( + ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, + ::std::unique_ptr<Expr> condition, ::std::unique_ptr<BlockExpr> loop_block, + Location locus, LoopLabel loop_label = LoopLabel::error (), + ::std::vector<Attribute> outer_attribs = ::std::vector<Attribute> ()) + : BaseLoopExpr (::std::move (loop_block), locus, ::std::move (loop_label), + ::std::move (outer_attribs)), + match_arm_patterns (::std::move (match_arm_patterns)), + condition (::std::move (condition)) + {} + + // Copy constructor with clone + WhileLetLoopExpr (WhileLetLoopExpr const &other) + : BaseLoopExpr (other), + /*match_arm_patterns(other.match_arm_patterns),*/ condition ( + other.condition->clone_expr ()) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + + for (const auto &e : other.match_arm_patterns) + { + match_arm_patterns.push_back (e->clone_pattern ()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone pointers + WhileLetLoopExpr &operator= (WhileLetLoopExpr const &other) + { + BaseLoopExpr::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + condition = other.condition->clone_expr (); + // loop_block = other.loop_block->clone_block_expr(); + // loop_label = other.loop_label; + // outer_attrs = other.outer_attrs; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + + for (const auto &e : other.match_arm_patterns) + { + match_arm_patterns.push_back (e->clone_pattern ()); + } + + return *this; + } + + // move constructors + WhileLetLoopExpr (WhileLetLoopExpr &&other) = default; + WhileLetLoopExpr &operator= (WhileLetLoopExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual WhileLetLoopExpr *clone_expr_impl () const OVERRIDE + { + return new WhileLetLoopExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual WhileLetLoopExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new WhileLetLoopExpr (*this); + } +}; + +// For loop expression AST node (iterator loop) +class ForLoopExpr : public BaseLoopExpr +{ + // Pattern pattern; + ::std::unique_ptr<Pattern> pattern; + // Expr* iterator_expr; + ::std::unique_ptr<Expr> iterator_expr; + +public: + /*~ForLoopExpr() { + delete iterator_expr; + }*/ + + ::std::string as_string () const; + + // Constructor with loop label + ForLoopExpr (::std::unique_ptr<Pattern> loop_pattern, + ::std::unique_ptr<Expr> iterator_expr, + ::std::unique_ptr<BlockExpr> loop_body, Location locus, + LoopLabel loop_label = LoopLabel::error (), + ::std::vector<Attribute> outer_attribs + = ::std::vector<Attribute> ()) + : BaseLoopExpr (::std::move (loop_body), locus, ::std::move (loop_label), + ::std::move (outer_attribs)), + pattern (::std::move (loop_pattern)), + iterator_expr (::std::move (iterator_expr)) + {} + + // Copy constructor with clone + ForLoopExpr (ForLoopExpr const &other) + : BaseLoopExpr (other), pattern (other.pattern->clone_pattern ()), + iterator_expr (other.iterator_expr->clone_expr ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + ForLoopExpr &operator= (ForLoopExpr const &other) + { + BaseLoopExpr::operator= (other); + pattern = other.pattern->clone_pattern (); + iterator_expr = other.iterator_expr->clone_expr (); + /*loop_block = other.loop_block->clone_block_expr(); + loop_label = other.loop_label; + outer_attrs = other.outer_attrs;*/ + + return *this; + } + + // move constructors + ForLoopExpr (ForLoopExpr &&other) = default; + ForLoopExpr &operator= (ForLoopExpr &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ForLoopExpr *clone_expr_impl () const OVERRIDE + { + return new ForLoopExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ForLoopExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new ForLoopExpr (*this); + } +}; + +// forward decl for IfExpr +class IfLetExpr; + +// Base if expression with no "else" or "if let" AST node +class IfExpr : public ExprWithBlock +{ + /*Expr* condition; + BlockExpr* if_block;*/ + ::std::unique_ptr<Expr> condition; + ::std::unique_ptr<BlockExpr> if_block; + /*union { + BlockExpr else_block; + IfExpr* if_expr; + IfLetExpr if_let_expr; + } consequent_block;*/ + + Location locus; + +public: + /*virtual ~IfExpr() { + delete condition; + delete if_block; + }*/ + + ::std::string as_string () const; + + IfExpr (::std::unique_ptr<Expr> condition, + ::std::unique_ptr<BlockExpr> if_block, Location locus) + : ExprWithBlock (::std::vector<Attribute> ()), + condition (::std::move (condition)), if_block (::std::move (if_block)), + locus (locus) + {} + // outer attributes are never allowed on IfExprs + + // Copy constructor with clone + IfExpr (IfExpr const &other) + : ExprWithBlock (other), condition (other.condition->clone_expr ()), + if_block (other.if_block->clone_block_expr ()), locus (other.locus) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone expressions + IfExpr &operator= (IfExpr const &other) + { + ExprWithBlock::operator= (other); + condition = other.condition->clone_expr (); + if_block = other.if_block->clone_block_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + IfExpr (IfExpr &&other) = default; + IfExpr &operator= (IfExpr &&other) = default; + + // Unique pointer custom clone function + ::std::unique_ptr<IfExpr> clone_if_expr () const + { + return ::std::unique_ptr<IfExpr> (clone_if_expr_impl ()); + } + + /* Note that multiple "else if"s are handled via nested ASTs rather than a + * vector of else ifs - i.e. not like a switch statement. TODO - is this a + * better approach? or does it not parse correctly and have downsides? */ + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExpr *clone_expr_impl () const OVERRIDE + { + return new IfExpr (*this); + } + + // Base clone function but still concrete as concrete base class + virtual IfExpr *clone_if_expr_impl () const { return new IfExpr (*this); } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new IfExpr (*this); + } +}; + +// If expression with an ending "else" expression AST node (trailing) +class IfExprConseqElse : public IfExpr +{ + // BlockExpr* else_block; + ::std::unique_ptr<BlockExpr> else_block; + +public: + /*~IfExprConseqElse() { + delete else_block; + }*/ + + ::std::string as_string () const; + + IfExprConseqElse (::std::unique_ptr<Expr> condition, + ::std::unique_ptr<BlockExpr> if_block, + ::std::unique_ptr<BlockExpr> else_block, Location locus) + : IfExpr (::std::move (condition), ::std::move (if_block), locus), + else_block (::std::move (else_block)) + {} + // again, outer attributes not allowed + + // Copy constructor with clone + IfExprConseqElse (IfExprConseqElse const &other) + : IfExpr (other), else_block (other.else_block->clone_block_expr ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator with cloning + IfExprConseqElse &operator= (IfExprConseqElse const &other) + { + IfExpr::operator= (other); + // condition = other.condition->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + else_block = other.else_block->clone_block_expr (); + + return *this; + } + + // move constructors + IfExprConseqElse (IfExprConseqElse &&other) = default; + IfExprConseqElse &operator= (IfExprConseqElse &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExprConseqElse *clone_expr_impl () const OVERRIDE + { + return new IfExprConseqElse (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExprConseqElse *clone_expr_with_block_impl () const OVERRIDE + { + return new IfExprConseqElse (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExprConseqElse *clone_if_expr_impl () const OVERRIDE + { + return new IfExprConseqElse (*this); + } +}; + +// If expression with an ending "else if" expression AST node +class IfExprConseqIf : public IfExpr +{ + // IfExpr* if_expr; + ::std::unique_ptr<IfExpr> if_expr; + +public: + /*~IfExprConseqIf() { + delete if_expr; + }*/ + + ::std::string as_string () const; + + IfExprConseqIf (::std::unique_ptr<Expr> condition, + ::std::unique_ptr<BlockExpr> if_block, + ::std::unique_ptr<IfExpr> conseq_if_expr, Location locus) + : IfExpr (::std::move (condition), ::std::move (if_block), locus), + if_expr (::std::move (conseq_if_expr)) + {} + // outer attributes not allowed + + // Copy constructor with clone + IfExprConseqIf (IfExprConseqIf const &other) + : IfExpr (other), if_expr (other.if_expr->clone_if_expr ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to use clone + IfExprConseqIf &operator= (IfExprConseqIf const &other) + { + IfExpr::operator= (other); + // condition = other.condition->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_expr = other.if_expr->clone_if_expr (); + + return *this; + } + + // move constructors + IfExprConseqIf (IfExprConseqIf &&other) = default; + IfExprConseqIf &operator= (IfExprConseqIf &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExprConseqIf *clone_expr_impl () const OVERRIDE + { + return new IfExprConseqIf (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExprConseqIf *clone_expr_with_block_impl () const OVERRIDE + { + return new IfExprConseqIf (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExprConseqIf *clone_if_expr_impl () const OVERRIDE + { + return new IfExprConseqIf (*this); + } +}; + +// Basic "if let" expression AST node with no else +class IfLetExpr : public ExprWithBlock +{ + // MatchArmPatterns patterns; + ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns; // inlined + /*Expr* value; + BlockExpr* if_block;*/ + ::std::unique_ptr<Expr> value; + ::std::unique_ptr<BlockExpr> if_block; + /*union { + BlockExpr else_block; + IfExpr if_expr; + IfLetExpr* if_let_expr; + } consequent_block;*/ + + Location locus; + +public: + ::std::string as_string () const; + + IfLetExpr (::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, + ::std::unique_ptr<Expr> value, + ::std::unique_ptr<BlockExpr> if_block, Location locus) + : ExprWithBlock (::std::vector<Attribute> ()), + match_arm_patterns (::std::move (match_arm_patterns)), + value (::std::move (value)), if_block (::std::move (if_block)), + locus (locus) + {} + // outer attributes not allowed on if let exprs either + + // copy constructor with clone + IfLetExpr (IfLetExpr const &other) + : ExprWithBlock (other), + /*match_arm_patterns(other.match_arm_patterns),*/ value ( + other.value->clone_expr ()), + if_block (other.if_block->clone_block_expr ()), locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + + for (const auto &e : other.match_arm_patterns) + { + match_arm_patterns.push_back (e->clone_pattern ()); + } + } + + // destructor - define here if required + + // overload assignment operator to clone + IfLetExpr &operator= (IfLetExpr const &other) + { + ExprWithBlock::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + value = other.value->clone_expr (); + if_block = other.if_block->clone_block_expr (); + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + + for (const auto &e : other.match_arm_patterns) + { + match_arm_patterns.push_back (e->clone_pattern ()); + } + + return *this; + } + + // move constructors + IfLetExpr (IfLetExpr &&other) = default; + IfLetExpr &operator= (IfLetExpr &&other) = default; + + // Unique pointer custom clone function + ::std::unique_ptr<IfLetExpr> clone_if_let_expr () const + { + return ::std::unique_ptr<IfLetExpr> (clone_if_let_expr_impl ()); + } + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExpr *clone_expr_impl () const OVERRIDE + { + return new IfLetExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new IfLetExpr (*this); + } + + // Base clone function but still concrete as concrete base class + virtual IfLetExpr *clone_if_let_expr_impl () const + { + return new IfLetExpr (*this); + } +}; + +// If expression with an ending "else if let" expression AST node +class IfExprConseqIfLet : public IfExpr +{ + // IfLetExpr* if_let_expr; + ::std::unique_ptr<IfLetExpr> if_let_expr; + +public: + /*~IfExprIfConseqIfLet() { + delete if_let_expr; + }*/ + + ::std::string as_string () const; + + IfExprConseqIfLet (::std::unique_ptr<Expr> condition, + ::std::unique_ptr<BlockExpr> if_block, + ::std::unique_ptr<IfLetExpr> conseq_if_let_expr, + Location locus) + : IfExpr (::std::move (condition), ::std::move (if_block), locus), + if_let_expr (::std::move (conseq_if_let_expr)) + {} + // outer attributes not allowed + + // Copy constructor with clone + IfExprConseqIfLet (IfExprConseqIfLet const &other) + : IfExpr (other), if_let_expr (other.if_let_expr->clone_if_let_expr ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to use clone + IfExprConseqIfLet &operator= (IfExprConseqIfLet const &other) + { + IfExpr::operator= (other); + // condition = other.condition->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_let_expr = other.if_let_expr->clone_if_let_expr (); + + return *this; + } + + // move constructors + IfExprConseqIfLet (IfExprConseqIfLet &&other) = default; + IfExprConseqIfLet &operator= (IfExprConseqIfLet &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExprConseqIfLet *clone_expr_impl () const OVERRIDE + { + return new IfExprConseqIfLet (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExprConseqIfLet *clone_expr_with_block_impl () const OVERRIDE + { + return new IfExprConseqIfLet (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfExprConseqIfLet *clone_if_expr_impl () const OVERRIDE + { + return new IfExprConseqIfLet (*this); + } +}; + +// AST node representing "if let" expression with an "else" expression at the +// end +class IfLetExprConseqElse : public IfLetExpr +{ + // BlockExpr* else_block; + ::std::unique_ptr<BlockExpr> else_block; + +public: + /*~IfLetExprConseqElse() { + delete else_block; + }*/ + + ::std::string as_string () const; + + IfLetExprConseqElse ( + ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, + ::std::unique_ptr<Expr> value, ::std::unique_ptr<BlockExpr> if_block, + ::std::unique_ptr<BlockExpr> else_block, Location locus) + : IfLetExpr (::std::move (match_arm_patterns), ::std::move (value), + ::std::move (if_block), locus), + else_block (::std::move (else_block)) + {} + // outer attributes not allowed + + // copy constructor with clone + IfLetExprConseqElse (IfLetExprConseqElse const &other) + : IfLetExpr (other), else_block (other.else_block->clone_block_expr ()) + {} + + // destructor - define here if required + + // overload assignment operator to clone + IfLetExprConseqElse &operator= (IfLetExprConseqElse const &other) + { + IfLetExpr::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + // value = other.value->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + else_block = other.else_block->clone_block_expr (); + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + IfLetExprConseqElse (IfLetExprConseqElse &&other) = default; + IfLetExprConseqElse &operator= (IfLetExprConseqElse &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExprConseqElse *clone_expr_impl () const OVERRIDE + { + return new IfLetExprConseqElse (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExprConseqElse *clone_expr_with_block_impl () const OVERRIDE + { + return new IfLetExprConseqElse (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExprConseqElse *clone_if_let_expr_impl () const OVERRIDE + { + return new IfLetExprConseqElse (*this); + } +}; + +// AST node representing "if let" expression with an "else if" expression at the +// end +class IfLetExprConseqIf : public IfLetExpr +{ + // IfExpr* if_expr; + ::std::unique_ptr<IfExpr> if_expr; + +public: + /*~IfLetExprConseqIf() { + delete if_expr; + }*/ + + ::std::string as_string () const; + + IfLetExprConseqIf ( + ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, + ::std::unique_ptr<Expr> value, ::std::unique_ptr<BlockExpr> if_block, + ::std::unique_ptr<IfExpr> if_expr, Location locus) + : IfLetExpr (::std::move (match_arm_patterns), ::std::move (value), + ::std::move (if_block), locus), + if_expr (::std::move (if_expr)) + {} + // again, outer attributes not allowed + + // copy constructor with clone + IfLetExprConseqIf (IfLetExprConseqIf const &other) + : IfLetExpr (other), if_expr (other.if_expr->clone_if_expr ()) + {} + + // destructor - define here if required + + // overload assignment operator to clone + IfLetExprConseqIf &operator= (IfLetExprConseqIf const &other) + { + IfLetExpr::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + // value = other.value->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_expr = other.if_expr->clone_if_expr (); + + return *this; + } + + // move constructors + IfLetExprConseqIf (IfLetExprConseqIf &&other) = default; + IfLetExprConseqIf &operator= (IfLetExprConseqIf &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExprConseqIf *clone_expr_impl () const OVERRIDE + { + return new IfLetExprConseqIf (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExprConseqIf *clone_expr_with_block_impl () const OVERRIDE + { + return new IfLetExprConseqIf (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExprConseqIf *clone_if_let_expr_impl () const OVERRIDE + { + return new IfLetExprConseqIf (*this); + } +}; + +// AST node representing "if let" expression with an "else if let" expression at +// the end +class IfLetExprConseqIfLet : public IfLetExpr +{ + // IfLetExpr* if_let_expr; + ::std::unique_ptr<IfLetExpr> if_let_expr; + +public: + /*~IfLetExprConseqIfLet() { + delete if_let_expr; + }*/ + + ::std::string as_string () const; + + IfLetExprConseqIfLet ( + ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, + ::std::unique_ptr<Expr> value, ::std::unique_ptr<BlockExpr> if_block, + ::std::unique_ptr<IfLetExpr> if_let_expr, Location locus) + : IfLetExpr (::std::move (match_arm_patterns), ::std::move (value), + ::std::move (if_block), locus), + if_let_expr (::std::move (if_let_expr)) + {} + // outer attributes not allowed + + // copy constructor with clone + IfLetExprConseqIfLet (IfLetExprConseqIfLet const &other) + : IfLetExpr (other), if_let_expr (other.if_let_expr->clone_if_let_expr ()) + {} + + // destructor - define here if required + + // overload assignment operator to clone + IfLetExprConseqIfLet &operator= (IfLetExprConseqIfLet const &other) + { + IfLetExpr::operator= (other); + // match_arm_patterns = other.match_arm_patterns; + // value = other.value->clone_expr(); + // if_block = other.if_block->clone_block_expr(); + if_let_expr = other.if_let_expr->clone_if_let_expr (); + + return *this; + } + + // move constructors + IfLetExprConseqIfLet (IfLetExprConseqIfLet &&other) = default; + IfLetExprConseqIfLet &operator= (IfLetExprConseqIfLet &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExprConseqIfLet *clone_expr_impl () const OVERRIDE + { + return new IfLetExprConseqIfLet (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExprConseqIfLet *clone_expr_with_block_impl () const OVERRIDE + { + return new IfLetExprConseqIfLet (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual IfLetExprConseqIfLet *clone_if_let_expr_impl () const OVERRIDE + { + return new IfLetExprConseqIfLet (*this); + } +}; + +// Match arm expression +struct MatchArm +{ +private: + ::std::vector<Attribute> outer_attrs; + // MatchArmPatterns patterns; + ::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns; // inlined + + // bool has_match_arm_guard; + // Expr* match_arm_guard; // inlined from MatchArmGuard + ::std::unique_ptr<Expr> guard_expr; + + // TODO: should this store location data? + +public: + /*~MatchArm() { + if (has_match_arm_guard) { + delete match_arm_guard; + } + }*/ + + // Returns whether the MatchArm has a match arm guard expression + inline bool has_match_arm_guard () const { return guard_expr != NULL; } + + // Constructor for match arm with a guard expression + MatchArm (::std::vector< ::std::unique_ptr<Pattern> > match_arm_patterns, + ::std::unique_ptr<Expr> guard_expr = NULL, + ::std::vector<Attribute> outer_attrs = ::std::vector<Attribute> ()) + : outer_attrs (::std::move (outer_attrs)), + match_arm_patterns (::std::move (match_arm_patterns)), + guard_expr (::std::move (guard_expr)) + {} + + // Copy constructor with clone + MatchArm (MatchArm const &other) + : /*match_arm_patterns(other.match_arm_patterns),*/ outer_attrs ( + other.outer_attrs) + { + // guard to protect from null pointer dereference + if (other.guard_expr != NULL) + { + guard_expr = other.guard_expr->clone_expr (); + } + + // DEBUG + fprintf ( + stderr, + "started copy-constructing match arm (outer attrs, guard expr done)\n"); + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + + for (const auto &e : other.match_arm_patterns) + { + match_arm_patterns.push_back (e->clone_pattern ()); + + // DEBUG + fprintf (stderr, "successfully pushed back a match arm pattern\n"); + } + + // DEBUG + fprintf (stderr, "successfully copy-constructed match arm\n"); + } + + ~MatchArm () = default; + + // Overload assignment operator to clone + MatchArm &operator= (MatchArm const &other) + { + // match_arm_patterns = other.match_arm_patterns; + outer_attrs = other.outer_attrs; + guard_expr = other.guard_expr->clone_expr (); + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + match_arm_patterns.reserve (other.match_arm_patterns.size ()); + + for (const auto &e : other.match_arm_patterns) + { + match_arm_patterns.push_back (e->clone_pattern ()); + } + + return *this; + } + + // move constructors + MatchArm (MatchArm &&other) = default; + MatchArm &operator= (MatchArm &&other) = default; + + // Returns whether match arm is in an error state. + inline bool is_error () const { return match_arm_patterns.empty (); } + + // Creates a match arm in an error state. + static MatchArm create_error () + { + return MatchArm (::std::vector< ::std::unique_ptr<Pattern> > ()); + } + + ::std::string as_string () const; +}; + +// Base "match case" for a match expression - abstract +class MatchCase +{ + MatchArm arm; + +protected: + MatchCase (MatchArm arm) : arm (::std::move (arm)) {} + + // Should not require copy constructor or assignment operator overloading + + // Clone function implementation as pure virtual method + virtual MatchCase *clone_match_case_impl () const = 0; + +public: + virtual ~MatchCase () {} + + // Unique pointer custom clone function + ::std::unique_ptr<MatchCase> clone_match_case () const + { + // DEBUG + fprintf (stderr, "about to call clone match case impl\n"); + + return ::std::unique_ptr<MatchCase> (clone_match_case_impl ()); + } + + virtual ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) = 0; +}; + +// Block expression match case +class MatchCaseBlockExpr : public MatchCase +{ + // BlockExpr* block_expr; + ::std::unique_ptr<BlockExpr> block_expr; + + // TODO: should this store location data? + +public: + /*~MatchCaseBlockExpr() { + delete block_expr; + }*/ + + MatchCaseBlockExpr (MatchArm arm, ::std::unique_ptr<BlockExpr> block_expr) + : MatchCase (::std::move (arm)), block_expr (::std::move (block_expr)) + {} + + // Copy constructor requires clone + MatchCaseBlockExpr (MatchCaseBlockExpr const &other) + : MatchCase (other), block_expr (other.block_expr->clone_block_expr ()) + { + // DEBUG + fprintf (stderr, "successfully copy constructed match case expr\n"); + } + + // Destructor - define here if required + + // Overload assignment operator to have clone + MatchCaseBlockExpr &operator= (MatchCaseBlockExpr const &other) + { + MatchCase::operator= (other); + block_expr = other.block_expr->clone_block_expr (); + // arm = other.arm; + + return *this; + } + + // move constructors + MatchCaseBlockExpr (MatchCaseBlockExpr &&other) = default; + MatchCaseBlockExpr &operator= (MatchCaseBlockExpr &&other) = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MatchCaseBlockExpr *clone_match_case_impl () const OVERRIDE + { + // DEBUG + fprintf (stderr, "about to copy construct match case block expr\n"); + + return new MatchCaseBlockExpr (*this); + } +}; + +// Expression (except block expression) match case +class MatchCaseExpr : public MatchCase +{ + // Expr* expr; + ::std::unique_ptr<Expr> expr; + + // TODO: should this store location data? + +public: + /*~MatchCaseExpr() { + delete expr; + }*/ + + MatchCaseExpr (MatchArm arm, ::std::unique_ptr<Expr> expr) + : MatchCase (::std::move (arm)), expr (::std::move (expr)) + {} + + // Copy constructor requires clone + MatchCaseExpr (MatchCaseExpr const &other) + : MatchCase (other), expr (other.expr->clone_expr ()) + { + // DEBUG + fprintf (stderr, "successfully copy constructed match case expr\n"); + } + + // Destructor - define here if required + + // Overload assignment operator to have clone + MatchCaseExpr &operator= (MatchCaseExpr const &other) + { + MatchCase::operator= (other); + expr = other.expr->clone_expr (); + // arm = other.arm; + + return *this; + } + + // move constructors + MatchCaseExpr (MatchCaseExpr &&other) = default; + MatchCaseExpr &operator= (MatchCaseExpr &&other) = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MatchCaseExpr *clone_match_case_impl () const OVERRIDE + { + // DEBUG + fprintf (stderr, "about to copy construct match case expr\n"); + if (expr == NULL) + { + fprintf ( + stderr, + "warning: match case expr to be copy constructed has null expr!\n"); + } + + return new MatchCaseExpr (*this); + } +}; + +// Match expression AST node +class MatchExpr : public ExprWithBlock +{ + // Expr* branch_value; + ::std::unique_ptr<Expr> branch_value; + ::std::vector<Attribute> inner_attrs; + + // bool has_match_arms; + // MatchArms match_arms; + ::std::vector< ::std::unique_ptr<MatchCase> > + match_arms; // inlined from MatchArms + + Location locus; + +public: + /*~MatchExpr() { + delete branch_value; + }*/ + + ::std::string as_string () const; + + // Returns whether the match expression has any match arms. + inline bool has_match_arms () const { return !match_arms.empty (); } + + MatchExpr (::std::unique_ptr<Expr> branch_value, + ::std::vector< ::std::unique_ptr<MatchCase> > match_arms, + ::std::vector<Attribute> inner_attrs, + ::std::vector<Attribute> outer_attrs, Location locus) + : ExprWithBlock (::std::move (outer_attrs)), + branch_value (::std::move (branch_value)), + inner_attrs (::std::move (inner_attrs)), + match_arms (::std::move (match_arms)), locus (locus) + {} + + // Copy constructor requires clone due to unique_ptr + MatchExpr (MatchExpr const &other) + : ExprWithBlock (other), + branch_value ( + other.branch_value->clone_expr ()), /*match_arms(other.match_arms),*/ + inner_attrs (other.inner_attrs), locus (other.locus) + { + fprintf (stderr, + "copy constructor for matchexpr called - only match arm vector " + "copying after this\n"); + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + match_arms.reserve (other.match_arms.size ()); + + fprintf (stderr, "match expr: successfully reserved size\n"); + + for (const auto &e : other.match_arms) + { + match_arms.push_back (e->clone_match_case ()); + fprintf (stderr, "match expr: successfully pushed back a match case\n"); + } + + fprintf (stderr, "match expr: successfully pushed back all match cases\n"); + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone due to unique_ptr + MatchExpr &operator= (MatchExpr const &other) + { + ExprWithBlock::operator= (other); + branch_value = other.branch_value->clone_expr (); + // match_arms = other.match_arms; + inner_attrs = other.inner_attrs; + // outer_attrs = other.outer_attrs; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + match_arms.reserve (other.match_arms.size ()); + + for (const auto &e : other.match_arms) + { + match_arms.push_back (e->clone_match_case ()); + } + + return *this; + } + + // move constructors + MatchExpr (MatchExpr &&other) = default; + MatchExpr &operator= (MatchExpr &&other) = default; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MatchExpr *clone_expr_impl () const OVERRIDE + { + return new MatchExpr (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual MatchExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new MatchExpr (*this); + } +}; + +// Await expression AST node (pseudo-member variable access) +class AwaitExpr : public ExprWithoutBlock +{ + ::std::unique_ptr<Expr> awaited_expr; + + Location locus; + +public: + // TODO: ensure outer attributes are actually allowed + AwaitExpr (::std::unique_ptr<Expr> awaited_expr, + ::std::vector<Attribute> outer_attrs, Location locus) + : ExprWithoutBlock (::std::move (outer_attrs)), + awaited_expr (::std::move (awaited_expr)), locus (locus) + {} + + // copy constructor with clone + AwaitExpr (AwaitExpr const &other) + : ExprWithoutBlock (other), + awaited_expr (other.awaited_expr->clone_expr ()), locus (other.locus) + {} + + // destructor - define here if required + + // overloaded assignment operator with clone + AwaitExpr &operator= (AwaitExpr const &other) + { + ExprWithoutBlock::operator= (other); + awaited_expr = other.awaited_expr->clone_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + AwaitExpr (AwaitExpr &&other) = default; + AwaitExpr &operator= (AwaitExpr &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual AwaitExpr *clone_expr_without_block_impl () const OVERRIDE + { + return new AwaitExpr (*this); + } +}; + +// Async block expression AST node (block expr that evaluates to a future) +class AsyncBlockExpr : public ExprWithBlock +{ + // TODO: should this extend BlockExpr rather than be a composite of it? + bool has_move; + ::std::unique_ptr<BlockExpr> block_expr; + + Location locus; + +public: + AsyncBlockExpr (::std::unique_ptr<BlockExpr> block_expr, bool has_move, + ::std::vector<Attribute> outer_attrs, Location locus) + : ExprWithBlock (::std::move (outer_attrs)), has_move (has_move), + block_expr (::std::move (block_expr)), locus (locus) + {} + + // copy constructor with clone + AsyncBlockExpr (AsyncBlockExpr const &other) + : ExprWithBlock (other), has_move (other.has_move), + block_expr (other.block_expr->clone_block_expr ()), locus (other.locus) + {} + + // destructor - define if required + + // overloaded assignment operator to clone + AsyncBlockExpr &operator= (AsyncBlockExpr const &other) + { + ExprWithBlock::operator= (other); + has_move = other.has_move; + block_expr = other.block_expr->clone_block_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + AsyncBlockExpr (AsyncBlockExpr &&other) = default; + AsyncBlockExpr &operator= (AsyncBlockExpr &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual AsyncBlockExpr *clone_expr_with_block_impl () const OVERRIDE + { + return new AsyncBlockExpr (*this); + } +}; +} // namespace AST +} // namespace Rust #endif diff --git a/gcc/rust/ast/rust-macro.h b/gcc/rust/ast/rust-macro.h index 727b195..fe5b5d8 100644 --- a/gcc/rust/ast/rust-macro.h +++ b/gcc/rust/ast/rust-macro.h @@ -4,584 +4,647 @@ #include "rust-ast.h" namespace Rust { - namespace AST { - // Decls as definitions moved to rust-ast.h - class MacroItem; - class MacroInvocationSemi; - - enum MacroFragSpec { - BLOCK, - EXPR, - IDENT, - ITEM, - LIFETIME, - LITERAL, - META, - PAT, - PATH, - STMT, - TT, - TY, - VIS, - INVALID // not really a specifier, but used to mark invalid one passed in - }; - - inline MacroFragSpec get_frag_spec_from_str(::std::string str) { - if (str == "block") - return BLOCK; - else if (str == "expr") - return EXPR; - else if (str == "ident") - return IDENT; - else if (str == "item") - return ITEM; - else if (str == "lifetime") - return LIFETIME; - else if (str == "literal") - return LITERAL; - else if (str == "meta") - return META; - else if (str == "pat") - return PAT; - else if (str == "path") - return PATH; - else if (str == "stmt") - return STMT; - else if (str == "tt") - return TT; - else if (str == "ty") - return TY; - else if (str == "vis") - return VIS; - else { - // error_at("invalid string '%s' used as fragment specifier", str->c_str()); - return INVALID; - } - } - - // A macro match that has an identifier and fragment spec - class MacroMatchFragment : public MacroMatch { - Identifier ident; - MacroFragSpec frag_spec; - - // TODO: should store location information? - - public: - MacroMatchFragment(Identifier ident, MacroFragSpec frag_spec) : - ident(::std::move(ident)), frag_spec(frag_spec) {} - - // Returns whether macro match fragment is in an error state. - inline bool is_error() const { - return frag_spec == INVALID; - } - - // Creates an error state macro match fragment. - static MacroMatchFragment create_error() { - return MacroMatchFragment(::std::string(""), INVALID); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroMatchFragment* clone_macro_match_impl() const OVERRIDE { - return new MacroMatchFragment(*this); - } - }; - - // A repetition macro match - class MacroMatchRepetition : public MacroMatch { - public: - enum MacroRepOp { NONE, ASTERISK, PLUS, QUESTION_MARK }; - - private: - //::std::vector<MacroMatch> matches; - ::std::vector< ::std::unique_ptr<MacroMatch> > matches; - MacroRepOp op; - - // bool has_sep; - typedef Token MacroRepSep; - // any token except delimiters and repetition operators - ::std::unique_ptr<MacroRepSep> sep; - - // TODO: should store location information? - - public: - // Returns whether macro match repetition has separator token. - inline bool has_sep() const { - return sep != NULL; - } - - MacroMatchRepetition(::std::vector< ::std::unique_ptr<MacroMatch> > matches, - MacroRepOp op, ::std::unique_ptr<MacroRepSep> sep) : - matches(::std::move(matches)), - op(op), sep(::std::move(sep)) {} - - // Copy constructor with clone - MacroMatchRepetition(MacroMatchRepetition const& other) : - /*matches(other.matches),*/ op(other.op), sep(other.sep->clone_token()) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - matches.reserve(other.matches.size()); - - for (const auto& e : other.matches) { - matches.push_back(e->clone_macro_match()); - } - } - - // Destructor - define here if required - - // Overloaded assignment operator to clone - MacroMatchRepetition& operator=(MacroMatchRepetition const& other) { - // matches = other.matches; // TODO: this needs to clone somehow? - op = other.op; - sep = other.sep->clone_token(); - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - matches.reserve(other.matches.size()); - - for (const auto& e : other.matches) { - matches.push_back(e->clone_macro_match()); - } - - return *this; - } - - // move constructors - MacroMatchRepetition(MacroMatchRepetition&& other) = default; - MacroMatchRepetition& operator=(MacroMatchRepetition&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroMatchRepetition* clone_macro_match_impl() const OVERRIDE { - return new MacroMatchRepetition(*this); - } - }; - - // can't inline due to polymorphism - class MacroMatcher : public MacroMatch { - DelimType delim_type; - //::std::vector<MacroMatch> matches; - ::std::vector< ::std::unique_ptr<MacroMatch> > matches; - - // TODO: think of way to mark invalid that doesn't take up more space - bool is_invalid; - - // TODO: should store location information? - - public: - MacroMatcher( - DelimType delim_type, ::std::vector< ::std::unique_ptr<MacroMatch> > matches) : - delim_type(delim_type), - matches(::std::move(matches)), is_invalid(false) {} - - // copy constructor with vector clone - MacroMatcher(MacroMatcher const& other) : delim_type(other.delim_type) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - matches.reserve(other.matches.size()); - - for (const auto& e : other.matches) { - matches.push_back(e->clone_macro_match()); - } - } - - // overloaded assignment operator with vector clone - MacroMatcher& operator=(MacroMatcher const& other) { - delim_type = other.delim_type; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - matches.reserve(other.matches.size()); - - for (const auto& e : other.matches) { - matches.push_back(e->clone_macro_match()); - } - - return *this; - } - - // move constructors - MacroMatcher(MacroMatcher&& other) = default; - MacroMatcher& operator=(MacroMatcher&& other) = default; - - // Creates an error state macro matcher. - static MacroMatcher create_error() { - return MacroMatcher(true); - } - - // Returns whether MacroMatcher is in an error state. - inline bool is_error() const { - return is_invalid; - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroMatcher* clone_macro_match_impl() const OVERRIDE { - return new MacroMatcher(*this); - } - - // constructor only used to create error matcher - MacroMatcher(bool is_invalid) : delim_type(PARENS), is_invalid(is_invalid) {} - }; - - // TODO: inline? - struct MacroTranscriber { - private: - DelimTokenTree token_tree; - - // TODO: should store location information? - - public: - MacroTranscriber(DelimTokenTree token_tree) : token_tree(::std::move(token_tree)) {} - - ::std::string as_string() const { - return token_tree.as_string(); - } - }; - - // A macro rule? Matcher and transcriber pair? - struct MacroRule { - private: - MacroMatcher matcher; - MacroTranscriber transcriber; - - // TODO: should store location information? - - public: - MacroRule(MacroMatcher matcher, MacroTranscriber transcriber) : - matcher(::std::move(matcher)), transcriber(::std::move(transcriber)) {} - - // Returns whether macro rule is in error state. - inline bool is_error() const { - return matcher.is_error(); - } - - // Creates an error state macro rule. - static MacroRule create_error() { - return MacroRule( - MacroMatcher::create_error(), MacroTranscriber(DelimTokenTree::create_empty())); - } - - ::std::string as_string() const; - }; - - // A macro rules definition item AST node - class MacroRulesDefinition : public MacroItem { - Identifier rule_name; - // MacroRulesDef rules_def; // TODO: inline - // only curly without required semicolon at end - DelimType delim_type; - // MacroRules rules; - ::std::vector<MacroRule> rules; // inlined form - - Location locus; - - public: - ::std::string as_string() const; - - MacroRulesDefinition(Identifier rule_name, DelimType delim_type, - ::std::vector<MacroRule> rules, ::std::vector<Attribute> outer_attrs, Location locus) : - MacroItem(::std::move(outer_attrs)), - rule_name(::std::move(rule_name)), delim_type(delim_type), rules(::std::move(rules)), - locus(locus) {} - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroRulesDefinition* clone_item_impl() const OVERRIDE { - return new MacroRulesDefinition(*this); - } - }; - - // AST node of a macro invocation, which is replaced by the macro result at compile time - class MacroInvocation - : public TypeNoBounds - , public Pattern - , public ExprWithoutBlock { - SimplePath path; - DelimTokenTree token_tree; - - Location locus; - - public: - ::std::string as_string() const; - - MacroInvocation(SimplePath path, DelimTokenTree token_tree, - ::std::vector<Attribute> outer_attrs, Location locus) : - ExprWithoutBlock(::std::move(outer_attrs)), - path(::std::move(path)), token_tree(::std::move(token_tree)), locus(locus) {} - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_pattern_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_expr_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_expr_without_block_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_type_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual MacroInvocation* clone_type_no_bounds_impl() const OVERRIDE { - return new MacroInvocation(*this); - } - }; - - // more generic meta item path-only form - class MetaItemPath : public MetaItem { - SimplePath path; - - public: - MetaItemPath(SimplePath path) : path(::std::move(path)) {} - - ::std::string as_string() const OVERRIDE { - return path.as_string(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // HACK: used to simplify parsing - returns non-empty only in this case - virtual SimplePath to_path_item() const OVERRIDE { - // this should copy construct - TODO ensure it does - return path; - } - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaItemPath* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaItemPath(*this); - } - }; - - // more generic meta item sequence form - class MetaItemSeq : public MetaItem { - SimplePath path; - ::std::vector< ::std::unique_ptr<MetaItemInner> > seq; - - public: - MetaItemSeq(SimplePath path, ::std::vector< ::std::unique_ptr<MetaItemInner> > seq) : - path(::std::move(path)), seq(::std::move(seq)) {} - - // copy constructor with vector clone - MetaItemSeq(const MetaItemSeq& other) : path(other.path) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - seq.reserve(other.seq.size()); - - for (const auto& e : other.seq) { - seq.push_back(e->clone_meta_item_inner()); - } - } - - // destructor definition not required - - // overloaded assignment operator with vector clone - MetaItemSeq& operator=(const MetaItemSeq& other) { - MetaItem::operator=(other); - path = other.path; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - seq.reserve(other.seq.size()); - - for (const auto& e : other.seq) { - seq.push_back(e->clone_meta_item_inner()); - } - - return *this; - } - - // default move constructors - MetaItemSeq(MetaItemSeq&& other) = default; - MetaItemSeq& operator=(MetaItemSeq&& other) = default; - - ::std::string as_string() const OVERRIDE; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaItemSeq* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaItemSeq(*this); - } - }; - - // Preferred specialisation for single-identifier meta items. - class MetaWord : public MetaItem { - Identifier ident; - - public: - MetaWord(Identifier ident) : ident(::std::move(ident)) {} - - ::std::string as_string() const OVERRIDE { - return ident; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaWord* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaWord(*this); - } - }; - - // Preferred specialisation for "identifier '=' string literal" meta items. - class MetaNameValueStr : public MetaItem { - Identifier ident; - ::std::string str; - - public: - MetaNameValueStr(Identifier ident, ::std::string str) : - ident(::std::move(ident)), str(::std::move(str)) {} - - ::std::string as_string() const OVERRIDE { - return ident + " = " + str; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - // HACK: used to simplify parsing - creates a copy of this - virtual MetaNameValueStr* to_meta_name_value_str() const OVERRIDE { - return clone_meta_item_inner_impl(); - } - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaNameValueStr* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaNameValueStr(*this); - } - }; - - // doubles up as MetaListIdents - determine via iterating through each path? - // Preferred specialisation for "identifier '(' SimplePath, SimplePath, ... ')'" - class MetaListPaths : public MetaItem { - Identifier ident; - ::std::vector<SimplePath> paths; - - public: - MetaListPaths(Identifier ident, ::std::vector<SimplePath> paths) : - ident(::std::move(ident)), paths(::std::move(paths)) {} - - ::std::string as_string() const OVERRIDE; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - private: - bool check_path_exists_in_cfg(const Session& session, const SimplePath& path) const; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaListPaths* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaListPaths(*this); - } - }; - - // Preferred specialisation for "identifier '(' MetaNameValueStr, ... ')'" - class MetaListNameValueStr : public MetaItem { - Identifier ident; - ::std::vector<MetaNameValueStr> strs; - - public: - MetaListNameValueStr(Identifier ident, ::std::vector<MetaNameValueStr> strs) : - ident(::std::move(ident)), strs(::std::move(strs)) {} - - ::std::string as_string() const OVERRIDE; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - virtual bool check_cfg_predicate(const Session& session) const OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this type - virtual MetaListNameValueStr* clone_meta_item_inner_impl() const OVERRIDE { - return new MetaListNameValueStr(*this); - } - }; - - // Object that parses macros from a token stream. - struct MacroParser { - private: - ::std::vector< ::std::unique_ptr<Token> > token_stream; - // probably have to make this mutable (mutable int stream_pos) otherwise const has to be - // removed up to DelimTokenTree or further ok since this changing would have an effect on - // the results of the methods run (i.e. not logically const), the parsing methods - // shouldn't be const - int stream_pos; - - public: - MacroParser( - ::std::vector< ::std::unique_ptr<Token> > token_stream, int stream_start_pos = 0) : - token_stream(::std::move(token_stream)), - stream_pos(stream_start_pos) {} - - ~MacroParser() = default; - - ::std::vector< ::std::unique_ptr<MetaItemInner> > parse_meta_item_seq(); - - private: - // Parses a MetaItemInner. - ::std::unique_ptr<MetaItemInner> parse_meta_item_inner(); - // Returns whether token can end a meta item. - bool is_end_meta_item_tok(TokenId id) const; - // Parses a simple path. - SimplePath parse_simple_path(); - // Parses a segment of a simple path (but not scope resolution operator). - SimplePathSegment parse_simple_path_segment(); - // Parses a MetaItemLitExpr. - ::std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit(); - // Parses a literal. - Literal parse_literal(); - // Parses a meta item that begins with a simple path. - ::std::unique_ptr<MetaItem> parse_path_meta_item(); - - // TODO: should this be const? - ::std::unique_ptr<Token>& peek_token(int i = 0) { - return token_stream[stream_pos + i]; - } - - void skip_token(int i = 0) { - stream_pos += 1 + i; - } - }; +namespace AST { +// Decls as definitions moved to rust-ast.h +class MacroItem; +class MacroInvocationSemi; + +enum MacroFragSpec +{ + BLOCK, + EXPR, + IDENT, + ITEM, + LIFETIME, + LITERAL, + META, + PAT, + PATH, + STMT, + TT, + TY, + VIS, + INVALID // not really a specifier, but used to mark invalid one passed in +}; + +inline MacroFragSpec +get_frag_spec_from_str (::std::string str) +{ + if (str == "block") + return BLOCK; + else if (str == "expr") + return EXPR; + else if (str == "ident") + return IDENT; + else if (str == "item") + return ITEM; + else if (str == "lifetime") + return LIFETIME; + else if (str == "literal") + return LITERAL; + else if (str == "meta") + return META; + else if (str == "pat") + return PAT; + else if (str == "path") + return PATH; + else if (str == "stmt") + return STMT; + else if (str == "tt") + return TT; + else if (str == "ty") + return TY; + else if (str == "vis") + return VIS; + else + { + // error_at("invalid string '%s' used as fragment specifier", + // str->c_str()); + return INVALID; } } +// A macro match that has an identifier and fragment spec +class MacroMatchFragment : public MacroMatch +{ + Identifier ident; + MacroFragSpec frag_spec; + + // TODO: should store location information? + +public: + MacroMatchFragment (Identifier ident, MacroFragSpec frag_spec) + : ident (::std::move (ident)), frag_spec (frag_spec) + {} + + // Returns whether macro match fragment is in an error state. + inline bool is_error () const { return frag_spec == INVALID; } + + // Creates an error state macro match fragment. + static MacroMatchFragment create_error () + { + return MacroMatchFragment (::std::string (""), INVALID); + } + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroMatchFragment *clone_macro_match_impl () const OVERRIDE + { + return new MacroMatchFragment (*this); + } +}; + +// A repetition macro match +class MacroMatchRepetition : public MacroMatch +{ +public: + enum MacroRepOp + { + NONE, + ASTERISK, + PLUS, + QUESTION_MARK + }; + +private: + //::std::vector<MacroMatch> matches; + ::std::vector< ::std::unique_ptr<MacroMatch> > matches; + MacroRepOp op; + + // bool has_sep; + typedef Token MacroRepSep; + // any token except delimiters and repetition operators + ::std::unique_ptr<MacroRepSep> sep; + + // TODO: should store location information? + +public: + // Returns whether macro match repetition has separator token. + inline bool has_sep () const { return sep != NULL; } + + MacroMatchRepetition (::std::vector< ::std::unique_ptr<MacroMatch> > matches, + MacroRepOp op, ::std::unique_ptr<MacroRepSep> sep) + : matches (::std::move (matches)), op (op), sep (::std::move (sep)) + {} + + // Copy constructor with clone + MacroMatchRepetition (MacroMatchRepetition const &other) + : /*matches(other.matches),*/ op (other.op), sep (other.sep->clone_token ()) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + matches.reserve (other.matches.size ()); + + for (const auto &e : other.matches) + { + matches.push_back (e->clone_macro_match ()); + } + } + + // Destructor - define here if required + + // Overloaded assignment operator to clone + MacroMatchRepetition &operator= (MacroMatchRepetition const &other) + { + // matches = other.matches; // TODO: this needs to clone somehow? + op = other.op; + sep = other.sep->clone_token (); + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + matches.reserve (other.matches.size ()); + + for (const auto &e : other.matches) + { + matches.push_back (e->clone_macro_match ()); + } + + return *this; + } + + // move constructors + MacroMatchRepetition (MacroMatchRepetition &&other) = default; + MacroMatchRepetition &operator= (MacroMatchRepetition &&other) = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroMatchRepetition *clone_macro_match_impl () const OVERRIDE + { + return new MacroMatchRepetition (*this); + } +}; + +// can't inline due to polymorphism +class MacroMatcher : public MacroMatch +{ + DelimType delim_type; + //::std::vector<MacroMatch> matches; + ::std::vector< ::std::unique_ptr<MacroMatch> > matches; + + // TODO: think of way to mark invalid that doesn't take up more space + bool is_invalid; + + // TODO: should store location information? + +public: + MacroMatcher (DelimType delim_type, + ::std::vector< ::std::unique_ptr<MacroMatch> > matches) + : delim_type (delim_type), matches (::std::move (matches)), + is_invalid (false) + {} + + // copy constructor with vector clone + MacroMatcher (MacroMatcher const &other) : delim_type (other.delim_type) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + matches.reserve (other.matches.size ()); + + for (const auto &e : other.matches) + { + matches.push_back (e->clone_macro_match ()); + } + } + + // overloaded assignment operator with vector clone + MacroMatcher &operator= (MacroMatcher const &other) + { + delim_type = other.delim_type; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + matches.reserve (other.matches.size ()); + + for (const auto &e : other.matches) + { + matches.push_back (e->clone_macro_match ()); + } + + return *this; + } + + // move constructors + MacroMatcher (MacroMatcher &&other) = default; + MacroMatcher &operator= (MacroMatcher &&other) = default; + + // Creates an error state macro matcher. + static MacroMatcher create_error () { return MacroMatcher (true); } + + // Returns whether MacroMatcher is in an error state. + inline bool is_error () const { return is_invalid; } + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroMatcher *clone_macro_match_impl () const OVERRIDE + { + return new MacroMatcher (*this); + } + + // constructor only used to create error matcher + MacroMatcher (bool is_invalid) : delim_type (PARENS), is_invalid (is_invalid) + {} +}; + +// TODO: inline? +struct MacroTranscriber +{ +private: + DelimTokenTree token_tree; + + // TODO: should store location information? + +public: + MacroTranscriber (DelimTokenTree token_tree) + : token_tree (::std::move (token_tree)) + {} + + ::std::string as_string () const { return token_tree.as_string (); } +}; + +// A macro rule? Matcher and transcriber pair? +struct MacroRule +{ +private: + MacroMatcher matcher; + MacroTranscriber transcriber; + + // TODO: should store location information? + +public: + MacroRule (MacroMatcher matcher, MacroTranscriber transcriber) + : matcher (::std::move (matcher)), transcriber (::std::move (transcriber)) + {} + + // Returns whether macro rule is in error state. + inline bool is_error () const { return matcher.is_error (); } + + // Creates an error state macro rule. + static MacroRule create_error () + { + return MacroRule (MacroMatcher::create_error (), + MacroTranscriber (DelimTokenTree::create_empty ())); + } + + ::std::string as_string () const; +}; + +// A macro rules definition item AST node +class MacroRulesDefinition : public MacroItem +{ + Identifier rule_name; + // MacroRulesDef rules_def; // TODO: inline + // only curly without required semicolon at end + DelimType delim_type; + // MacroRules rules; + ::std::vector<MacroRule> rules; // inlined form + + Location locus; + +public: + ::std::string as_string () const; + + MacroRulesDefinition (Identifier rule_name, DelimType delim_type, + ::std::vector<MacroRule> rules, + ::std::vector<Attribute> outer_attrs, Location locus) + : MacroItem (::std::move (outer_attrs)), + rule_name (::std::move (rule_name)), delim_type (delim_type), + rules (::std::move (rules)), locus (locus) + {} + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroRulesDefinition *clone_item_impl () const OVERRIDE + { + return new MacroRulesDefinition (*this); + } +}; + +// AST node of a macro invocation, which is replaced by the macro result at +// compile time +class MacroInvocation : public TypeNoBounds, + public Pattern, + public ExprWithoutBlock +{ + SimplePath path; + DelimTokenTree token_tree; + + Location locus; + +public: + ::std::string as_string () const; + + MacroInvocation (SimplePath path, DelimTokenTree token_tree, + ::std::vector<Attribute> outer_attrs, Location locus) + : ExprWithoutBlock (::std::move (outer_attrs)), path (::std::move (path)), + token_tree (::std::move (token_tree)), locus (locus) + {} + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroInvocation *clone_pattern_impl () const OVERRIDE + { + return new MacroInvocation (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroInvocation *clone_expr_impl () const OVERRIDE + { + return new MacroInvocation (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroInvocation *clone_expr_without_block_impl () const OVERRIDE + { + return new MacroInvocation (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroInvocation *clone_type_impl () const OVERRIDE + { + return new MacroInvocation (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual MacroInvocation *clone_type_no_bounds_impl () const OVERRIDE + { + return new MacroInvocation (*this); + } +}; + +// more generic meta item path-only form +class MetaItemPath : public MetaItem +{ + SimplePath path; + +public: + MetaItemPath (SimplePath path) : path (::std::move (path)) {} + + ::std::string as_string () const OVERRIDE { return path.as_string (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + // HACK: used to simplify parsing - returns non-empty only in this case + virtual SimplePath to_path_item () const OVERRIDE + { + // this should copy construct - TODO ensure it does + return path; + } + + virtual bool check_cfg_predicate (const Session &session) const OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this type + virtual MetaItemPath *clone_meta_item_inner_impl () const OVERRIDE + { + return new MetaItemPath (*this); + } +}; + +// more generic meta item sequence form +class MetaItemSeq : public MetaItem +{ + SimplePath path; + ::std::vector< ::std::unique_ptr<MetaItemInner> > seq; + +public: + MetaItemSeq (SimplePath path, + ::std::vector< ::std::unique_ptr<MetaItemInner> > seq) + : path (::std::move (path)), seq (::std::move (seq)) + {} + + // copy constructor with vector clone + MetaItemSeq (const MetaItemSeq &other) : path (other.path) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + seq.reserve (other.seq.size ()); + + for (const auto &e : other.seq) + { + seq.push_back (e->clone_meta_item_inner ()); + } + } + + // destructor definition not required + + // overloaded assignment operator with vector clone + MetaItemSeq &operator= (const MetaItemSeq &other) + { + MetaItem::operator= (other); + path = other.path; + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + seq.reserve (other.seq.size ()); + + for (const auto &e : other.seq) + { + seq.push_back (e->clone_meta_item_inner ()); + } + + return *this; + } + + // default move constructors + MetaItemSeq (MetaItemSeq &&other) = default; + MetaItemSeq &operator= (MetaItemSeq &&other) = default; + + ::std::string as_string () const OVERRIDE; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + virtual bool check_cfg_predicate (const Session &session) const OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this type + virtual MetaItemSeq *clone_meta_item_inner_impl () const OVERRIDE + { + return new MetaItemSeq (*this); + } +}; + +// Preferred specialisation for single-identifier meta items. +class MetaWord : public MetaItem +{ + Identifier ident; + +public: + MetaWord (Identifier ident) : ident (::std::move (ident)) {} + + ::std::string as_string () const OVERRIDE { return ident; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + virtual bool check_cfg_predicate (const Session &session) const OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this type + virtual MetaWord *clone_meta_item_inner_impl () const OVERRIDE + { + return new MetaWord (*this); + } +}; + +// Preferred specialisation for "identifier '=' string literal" meta items. +class MetaNameValueStr : public MetaItem +{ + Identifier ident; + ::std::string str; + +public: + MetaNameValueStr (Identifier ident, ::std::string str) + : ident (::std::move (ident)), str (::std::move (str)) + {} + + ::std::string as_string () const OVERRIDE { return ident + " = " + str; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + // HACK: used to simplify parsing - creates a copy of this + virtual MetaNameValueStr *to_meta_name_value_str () const OVERRIDE + { + return clone_meta_item_inner_impl (); + } + + virtual bool check_cfg_predicate (const Session &session) const OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this type + virtual MetaNameValueStr *clone_meta_item_inner_impl () const OVERRIDE + { + return new MetaNameValueStr (*this); + } +}; + +// doubles up as MetaListIdents - determine via iterating through each path? +// Preferred specialisation for "identifier '(' SimplePath, SimplePath, ... ')'" +class MetaListPaths : public MetaItem +{ + Identifier ident; + ::std::vector<SimplePath> paths; + +public: + MetaListPaths (Identifier ident, ::std::vector<SimplePath> paths) + : ident (::std::move (ident)), paths (::std::move (paths)) + {} + + ::std::string as_string () const OVERRIDE; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + virtual bool check_cfg_predicate (const Session &session) const OVERRIDE; + +private: + bool check_path_exists_in_cfg (const Session &session, + const SimplePath &path) const; + +protected: + // Use covariance to implement clone function as returning this type + virtual MetaListPaths *clone_meta_item_inner_impl () const OVERRIDE + { + return new MetaListPaths (*this); + } +}; + +// Preferred specialisation for "identifier '(' MetaNameValueStr, ... ')'" +class MetaListNameValueStr : public MetaItem +{ + Identifier ident; + ::std::vector<MetaNameValueStr> strs; + +public: + MetaListNameValueStr (Identifier ident, ::std::vector<MetaNameValueStr> strs) + : ident (::std::move (ident)), strs (::std::move (strs)) + {} + + ::std::string as_string () const OVERRIDE; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + virtual bool check_cfg_predicate (const Session &session) const OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this type + virtual MetaListNameValueStr *clone_meta_item_inner_impl () const OVERRIDE + { + return new MetaListNameValueStr (*this); + } +}; + +// Object that parses macros from a token stream. +struct MacroParser +{ +private: + ::std::vector< ::std::unique_ptr<Token> > token_stream; + // probably have to make this mutable (mutable int stream_pos) otherwise const + // has to be removed up to DelimTokenTree or further ok since this changing + // would have an effect on the results of the methods run (i.e. not logically + // const), the parsing methods shouldn't be const + int stream_pos; + +public: + MacroParser (::std::vector< ::std::unique_ptr<Token> > token_stream, + int stream_start_pos = 0) + : token_stream (::std::move (token_stream)), stream_pos (stream_start_pos) + {} + + ~MacroParser () = default; + + ::std::vector< ::std::unique_ptr<MetaItemInner> > parse_meta_item_seq (); + +private: + // Parses a MetaItemInner. + ::std::unique_ptr<MetaItemInner> parse_meta_item_inner (); + // Returns whether token can end a meta item. + bool is_end_meta_item_tok (TokenId id) const; + // Parses a simple path. + SimplePath parse_simple_path (); + // Parses a segment of a simple path (but not scope resolution operator). + SimplePathSegment parse_simple_path_segment (); + // Parses a MetaItemLitExpr. + ::std::unique_ptr<MetaItemLitExpr> parse_meta_item_lit (); + // Parses a literal. + Literal parse_literal (); + // Parses a meta item that begins with a simple path. + ::std::unique_ptr<MetaItem> parse_path_meta_item (); + + // TODO: should this be const? + ::std::unique_ptr<Token> &peek_token (int i = 0) + { + return token_stream[stream_pos + i]; + } + + void skip_token (int i = 0) { stream_pos += 1 + i; } +}; +} // namespace AST +} // namespace Rust + #endif diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 6845603f..434ed62 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -1,7 +1,7 @@ #ifndef RUST_AST_PATH_H #define RUST_AST_PATH_H -/* "Path" (identifier within namespaces, essentially) handling. Required include for virtually all - * AST-related functionality. */ +/* "Path" (identifier within namespaces, essentially) handling. Required include + * for virtually all AST-related functionality. */ #include "rust-ast.h" @@ -9,795 +9,872 @@ #include <vector> namespace Rust { - namespace AST { - // make intellisense calm - /*typedef ::std::string Symbol; - typedef int Lifetime; - typedef int Type; - typedef int Binding;*/ - - // The "identifier" (not generic args) aspect of each path expression segment - class PathIdentSegment { - ::std::string segment_name; - - // TODO: should this have location info stored? - - // only allow identifiers, "super", "self", "Self", "crate", or "$crate" - public: - PathIdentSegment(::std::string segment_name) : segment_name(::std::move(segment_name)) {} - - /* TODO: insert check in constructor for this? Or is this a semantic error best handled - * then? */ - - // TODO: does this require visitor. pretty sure this isn't polymorphic, but not entirely - // sure - - // Creates an error PathIdentSegment. - static PathIdentSegment create_error() { - return PathIdentSegment(""); - } - - // Returns whether PathIdentSegment is in an error state. - inline bool is_error() const { - return segment_name.empty(); - } - - ::std::string as_string() const { - return segment_name; - } - }; - - // A binding of an identifier to a type used in generic arguments in paths - struct GenericArgsBinding { - private: - Identifier identifier; - // Type type; - ::std::unique_ptr<Type> type; - - Location locus; - - public: - // Returns whether binding is in an error state. - inline bool is_error() const { - return type == NULL; // and also identifier is empty, but cheaper computation - } - - // Creates an error state generic args binding. - static GenericArgsBinding create_error() { - return GenericArgsBinding("", NULL); - } - - // Pointer type for type in constructor to enable polymorphism - GenericArgsBinding( - Identifier ident, ::std::unique_ptr<Type> type_ptr, Location locus = Location()) : - identifier(::std::move(ident)), - type(::std::move(type_ptr)), locus(locus) {} - - // Copy constructor has to deep copy the type as it is a unique pointer - GenericArgsBinding(GenericArgsBinding const& other) : - identifier(other.identifier), type(other.type->clone_type()), locus(other.locus) {} - - // default destructor - ~GenericArgsBinding() = default; - - // Overload assignment operator to deep copy the pointed-to type - GenericArgsBinding& operator=(GenericArgsBinding const& other) { - identifier = other.identifier; - type = other.type->clone_type(); - locus = other.locus; - return *this; - } - - // move constructors - GenericArgsBinding(GenericArgsBinding&& other) = default; - GenericArgsBinding& operator=(GenericArgsBinding&& other) = default; - - ::std::string as_string() const; - }; - - // Generic arguments allowed in each path expression segment - inline? - struct GenericArgs { - ::std::vector<Lifetime> lifetime_args; - //::std::vector<Type> type_args; - ::std::vector< ::std::unique_ptr<Type> > type_args; - ::std::vector<GenericArgsBinding> binding_args; - - Location locus; - - public: - // Returns true if there are any generic arguments - inline bool has_generic_args() const { - return !(lifetime_args.empty() && type_args.empty() && binding_args.empty()); - } - - GenericArgs(::std::vector<Lifetime> lifetime_args, - ::std::vector< ::std::unique_ptr<Type> > type_args, - ::std::vector<GenericArgsBinding> binding_args, Location locus = Location()) : - lifetime_args(::std::move(lifetime_args)), - type_args(::std::move(type_args)), binding_args(::std::move(binding_args)), - locus(locus) {} - - // copy constructor with vector clone - GenericArgs(GenericArgs const& other) : - lifetime_args(other.lifetime_args), binding_args(other.binding_args), - locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_args.reserve(other.type_args.size()); - - for (const auto& e : other.type_args) { - type_args.push_back(e->clone_type()); - } - } - - ~GenericArgs() = default; - - // overloaded assignment operator to vector clone - GenericArgs& operator=(GenericArgs const& other) { - lifetime_args = other.lifetime_args; - binding_args = other.binding_args; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_args.reserve(other.type_args.size()); - - for (const auto& e : other.type_args) { - type_args.push_back(e->clone_type()); - } - - return *this; - } - - // move constructors - GenericArgs(GenericArgs&& other) = default; - GenericArgs& operator=(GenericArgs&& other) = default; - - // Creates an empty GenericArgs (no arguments) - static GenericArgs create_empty() { - return GenericArgs(::std::vector<Lifetime>(), - ::std::vector< ::std::unique_ptr<Type> >(), ::std::vector<GenericArgsBinding>()); - } - - ::std::string as_string() const; - }; - - // A segment of a path in expression, including an identifier aspect and maybe generic args - class PathExprSegment { // or should this extend PathIdentSegment? - private: - PathIdentSegment segment_name; - - // bool has_generic_args; - GenericArgs generic_args; - - Location locus; - - // TODO: does this require visitor? pretty sure not polymorphic - - public: - // Returns true if there are any generic arguments - inline bool has_generic_args() const { - return generic_args.has_generic_args(); - } - - // Constructor for segment (from IdentSegment and GenericArgs) - PathExprSegment(PathIdentSegment segment_name, Location locus = Location(), - GenericArgs generic_args = GenericArgs::create_empty()) : - segment_name(::std::move(segment_name)), - generic_args(::std::move(generic_args)), locus(locus) {} - - // Constructor for segment with generic arguments (from segment name and all args) - PathExprSegment(::std::string segment_name, Location locus, - ::std::vector<Lifetime> lifetime_args = ::std::vector<Lifetime>(), - ::std::vector< ::std::unique_ptr<Type> > type_args - = ::std::vector< ::std::unique_ptr<Type> >(), - ::std::vector<GenericArgsBinding> binding_args = ::std::vector<GenericArgsBinding>()) : - segment_name(PathIdentSegment(::std::move(segment_name))), - generic_args(GenericArgs( - ::std::move(lifetime_args), ::std::move(type_args), ::std::move(binding_args))), - locus(locus) {} - - // Returns whether path expression segment is in an error state. - inline bool is_error() const { - return segment_name.is_error(); - } - - // Creates an error-state path expression segment. - static PathExprSegment create_error() { - return PathExprSegment(PathIdentSegment::create_error()); - } - - ::std::string as_string() const; - - inline Location get_locus() const { - return locus; - } - }; - - // AST node representing a pattern that involves a "path" - abstract base class - class PathPattern : public Pattern { - ::std::vector<PathExprSegment> segments; - - protected: - PathPattern(::std::vector<PathExprSegment> segments) : segments(::std::move(segments)) {} - - // Returns whether path has segments. - inline bool has_segments() const { - 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; - - public: - /* Returns whether the path is a single segment (excluding qualified path initial as - * segment). */ - inline bool is_single_segment() const { - return segments.size() == 1; - } - - virtual ::std::string as_string() const; - }; - - // AST node representing a path-in-expression pattern (path that allows generic arguments) - class PathInExpression - : public PathPattern - , public PathExpr { - bool has_opening_scope_resolution; - - Location locus; - - public: - ::std::string as_string() const; - - // Constructor - PathInExpression(::std::vector<PathExprSegment> path_segments, - Location locus = Location(), bool has_opening_scope_resolution = false, - ::std::vector<Attribute> outer_attrs = ::std::vector<Attribute>()) : - PathPattern(::std::move(path_segments)), - PathExpr(::std::move(outer_attrs)), - has_opening_scope_resolution(has_opening_scope_resolution), locus(locus) {} - - // Creates an error state path in expression. - static PathInExpression create_error() { - return PathInExpression(::std::vector<PathExprSegment>()); - } - - // Returns whether path in expression is in an error state. - inline bool is_error() const { - return !has_segments(); - } - - /* Converts PathInExpression to SimplePath if possible (i.e. no generic arguments). - * Otherwise returns an empty SimplePath. */ - inline SimplePath as_simple_path() const { - /* delegate to parent class as can't access segments. however, - * QualifiedPathInExpression conversion to simple path wouldn't make sense, so the - * method in the parent class should be protected, not public. - * Have to pass in opening scope resolution as parent class has no access to it. */ - return convert_to_simple_path(has_opening_scope_resolution); - } - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual PathInExpression* clone_pattern_impl() const OVERRIDE { - return new PathInExpression(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual PathInExpression* clone_expr_without_block_impl() const OVERRIDE { - return new PathInExpression(*this); - } - }; - - // Base class for segments used in type paths - not abstract (represents an ident-only - // segment) - class TypePathSegment { - /* TODO: may have to unify TypePathSegment and PathExprSegment (which are mostly the - * same anyway) in order to resolve goddamn syntax ambiguities. - * One difference is that function on TypePathSegment is not allowed if GenericArgs are, - * so could disallow that in constructor, which won't give that much size overhead. */ - PathIdentSegment ident_segment; - - Location locus; - - protected: - // This is protected because it is only really used by derived classes, not the base. - bool has_separating_scope_resolution; - - // Clone function implementation - not pure virtual as overrided by subclasses - virtual TypePathSegment* clone_type_path_segment_impl() const { - return new TypePathSegment(*this); - } - - public: - virtual ~TypePathSegment() {} - - // Unique pointer custom clone function - ::std::unique_ptr<TypePathSegment> clone_type_path_segment() const { - return ::std::unique_ptr<TypePathSegment>(clone_type_path_segment_impl()); - } - - TypePathSegment( - PathIdentSegment ident_segment, bool has_separating_scope_resolution, Location locus) : - ident_segment(::std::move(ident_segment)), - locus(locus), has_separating_scope_resolution(has_separating_scope_resolution) {} - - TypePathSegment( - ::std::string segment_name, bool has_separating_scope_resolution, Location locus) : - ident_segment(PathIdentSegment(::std::move(segment_name))), - locus(locus), has_separating_scope_resolution(has_separating_scope_resolution) {} - - virtual ::std::string as_string() const { - return ident_segment.as_string(); - } - - // Returns whether the type path segment is in an error state. May be virtual in future. - inline bool is_error() const { - return ident_segment.is_error(); - } - - /* Returns whether segment is identifier only (as opposed to generic args or function). - Overriden in derived classes with other segments. */ - virtual bool is_ident_only() const { - return true; - } - - inline Location get_locus() const { - return locus; - } - - // not pure virtual as class not abstract - virtual void accept_vis(ASTVisitor& vis); - }; - - // Segment used in type path with generic args - class TypePathSegmentGeneric : public TypePathSegment { - GenericArgs generic_args; - - public: - inline bool has_generic_args() const { - return generic_args.has_generic_args(); - } - - bool is_ident_only() const { - return false; - } - - // Constructor with PathIdentSegment and GenericArgs - TypePathSegmentGeneric(PathIdentSegment ident_segment, - bool has_separating_scope_resolution, GenericArgs generic_args, Location locus) : - TypePathSegment(::std::move(ident_segment), has_separating_scope_resolution, locus), - generic_args(::std::move(generic_args)) {} - - // Constructor from segment name and all args - TypePathSegmentGeneric(::std::string segment_name, bool has_separating_scope_resolution, - ::std::vector<Lifetime> lifetime_args, - ::std::vector< ::std::unique_ptr<Type> > type_args, - ::std::vector<GenericArgsBinding> binding_args, Location locus) : - TypePathSegment(::std::move(segment_name), has_separating_scope_resolution, locus), - generic_args(GenericArgs( - ::std::move(lifetime_args), ::std::move(type_args), ::std::move(binding_args))) {} - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to override base class method - virtual TypePathSegmentGeneric* clone_type_path_segment_impl() const OVERRIDE { - return new TypePathSegmentGeneric(*this); - } - }; - - // A function as represented in a type path - struct TypePathFunction { - private: - // TODO: remove - /*bool has_inputs; - TypePathFnInputs inputs;*/ - //::std::vector<Type> inputs; // inlined from TypePathFnInputs - ::std::vector< ::std::unique_ptr<Type> > inputs; - - // bool has_type; - // Type type; - ::std::unique_ptr<Type> return_type; - - // FIXME: think of better way to mark as invalid than taking up storage - bool is_invalid; - - // TODO: should this have location info? - - protected: - // Constructor only used to create invalid type path functions. - TypePathFunction(bool is_invalid) : is_invalid(is_invalid) {} - - public: - // Returns whether the return type of the function has been specified. - inline bool has_return_type() const { - return return_type != NULL; - } - - // Returns whether the function has inputs. - inline bool has_inputs() const { - return !inputs.empty(); - } - - // Returns whether function is in an error state. - inline bool is_error() const { - return is_invalid; - } - - // Creates an error state function. - static TypePathFunction create_error() { - return TypePathFunction(true); - } - - // Constructor - TypePathFunction(::std::vector< ::std::unique_ptr<Type> > inputs, Type* type = NULL) : - inputs(::std::move(inputs)), return_type(type), is_invalid(false) {} - // FIXME: deprecated - - // Constructor - TypePathFunction( - ::std::vector< ::std::unique_ptr<Type> > inputs, ::std::unique_ptr<Type> type = NULL) : - inputs(::std::move(inputs)), - return_type(::std::move(type)), is_invalid(false) {} - - // Copy constructor with clone - TypePathFunction(TypePathFunction const& other) : - /*inputs(other.inputs),*/ return_type(other.return_type->clone_type()), - is_invalid(other.is_invalid) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - inputs.reserve(other.inputs.size()); - - for (const auto& e : other.inputs) { - inputs.push_back(e->clone_type()); - } - } - - ~TypePathFunction() = default; - - // Overloaded assignment operator to clone type - TypePathFunction& operator=(TypePathFunction const& other) { - // inputs = other.inputs; - return_type = other.return_type->clone_type(); - is_invalid = other.is_invalid; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - inputs.reserve(other.inputs.size()); - - for (const auto& e : other.inputs) { - inputs.push_back(e->clone_type()); - } - - return *this; - } - - // move constructors - TypePathFunction(TypePathFunction&& other) = default; - TypePathFunction& operator=(TypePathFunction&& other) = default; - - ::std::string as_string() const; - }; - - // Segment used in type path with a function argument - class TypePathSegmentFunction : public TypePathSegment { - TypePathFunction function_path; - - public: - // Constructor with PathIdentSegment and TypePathFn - TypePathSegmentFunction(PathIdentSegment ident_segment, - bool has_separating_scope_resolution, TypePathFunction function_path, Location locus) : - TypePathSegment(::std::move(ident_segment), has_separating_scope_resolution, locus), - function_path(::std::move(function_path)) {} - - // Constructor with segment name and TypePathFn - TypePathSegmentFunction(::std::string segment_name, bool has_separating_scope_resolution, - TypePathFunction function_path, Location locus) : - TypePathSegment(::std::move(segment_name), has_separating_scope_resolution, locus), - function_path(::std::move(function_path)) {} - - ::std::string as_string() const; - - bool is_ident_only() const { - return false; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to override base class method - virtual TypePathSegmentFunction* clone_type_path_segment_impl() const OVERRIDE { - return new TypePathSegmentFunction(*this); - } - }; - - // Path used inside types - class TypePath : public TypeNoBounds { - bool has_opening_scope_resolution; - ::std::vector< ::std::unique_ptr<TypePathSegment> > segments; - - Location locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TypePath* clone_type_impl() const OVERRIDE { - return new TypePath(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TypePath* clone_type_no_bounds_impl() const OVERRIDE { - return new TypePath(*this); - } - - public: - /* Returns whether the TypePath has an opening scope resolution operator (i.e. is global - * path or crate-relative path, not module-relative) */ - inline bool has_opening_scope_resolution_op() const { - return has_opening_scope_resolution; - } - - // Returns whether the TypePath is in an invalid state. - inline bool is_error() const { - return segments.empty(); - } - - // Creates an error state TypePath. - static TypePath create_error() { - return TypePath(::std::vector< ::std::unique_ptr<TypePathSegment> >(), Location()); - } - - // Constructor - TypePath(::std::vector< ::std::unique_ptr<TypePathSegment> > segments, Location locus, - bool has_opening_scope_resolution = false) : - has_opening_scope_resolution(has_opening_scope_resolution), - segments(::std::move(segments)), locus(locus) {} - - // Copy constructor with vector clone - TypePath(TypePath const& other) : - has_opening_scope_resolution(other.has_opening_scope_resolution), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - segments.reserve(other.segments.size()); - - for (const auto& e : other.segments) { - segments.push_back(e->clone_type_path_segment()); - } - } - - // Overloaded assignment operator with clone - TypePath& operator=(TypePath const& other) { - has_opening_scope_resolution = other.has_opening_scope_resolution; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - segments.reserve(other.segments.size()); - - for (const auto& e : other.segments) { - segments.push_back(e->clone_type_path_segment()); - } - - return *this; - } - - // move constructors - TypePath(TypePath&& other) = default; - TypePath& operator=(TypePath&& other) = default; - - ::std::string as_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; - - // Creates a trait bound with a clone of this type path as its only element. - virtual TraitBound* to_trait_bound(bool in_parens) const OVERRIDE; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - struct QualifiedPathType { - private: - // Type type_to_invoke_on; - ::std::unique_ptr<Type> type_to_invoke_on; - - // bool has_as_clause; - TypePath trait_path; - - Location locus; - - public: - // Constructor - QualifiedPathType(::std::unique_ptr<Type> invoke_on_type, Location locus = Location(), - TypePath trait_path = TypePath::create_error()) : - type_to_invoke_on(::std::move(invoke_on_type)), - trait_path(::std::move(trait_path)), locus(locus) {} - - // Copy constructor uses custom deep copy for Type to preserve polymorphism - QualifiedPathType(QualifiedPathType const& other) : - type_to_invoke_on(other.type_to_invoke_on->clone_type()), trait_path(other.trait_path), - locus(other.locus) {} - - // default destructor - ~QualifiedPathType() = default; - - // overload assignment operator to use custom clone method - QualifiedPathType& operator=(QualifiedPathType const& other) { - type_to_invoke_on = other.type_to_invoke_on->clone_type(); - trait_path = other.trait_path; - locus = other.locus; - return *this; - } - - // move constructor - QualifiedPathType(QualifiedPathType&& other) = default; - QualifiedPathType& operator=(QualifiedPathType&& other) = default; - - // Returns whether the qualified path type has a rebind as clause. - inline bool has_as_clause() const { - return !trait_path.is_error(); - } - - // Returns whether the qualified path type is in an error state. - inline bool is_error() const { - return type_to_invoke_on == NULL; - } - - // Creates an error state qualified path type. - static QualifiedPathType create_error() { - return QualifiedPathType(NULL); - } - - ::std::string as_string() const; - - inline Location get_locus() const { - return locus; - } - }; - - /* AST node representing a qualified path-in-expression pattern (path that allows specifying - * trait functions) */ - class QualifiedPathInExpression - : public PathPattern - , public PathExpr { - QualifiedPathType path_type; - - Location locus; - - public: - ::std::string as_string() const; - - QualifiedPathInExpression(QualifiedPathType qual_path_type, - ::std::vector<PathExprSegment> path_segments, Location locus = Location(), - ::std::vector<Attribute> outer_attrs = ::std::vector<Attribute>()) : - PathPattern(::std::move(path_segments)), - PathExpr(::std::move(outer_attrs)), path_type(::std::move(qual_path_type)), - locus(locus) {} - - // TODO: maybe make a shortcut constructor that has QualifiedPathType elements as params - - // Copy constructor, destructor, and assignment operator overload shouldn't be required - - // Returns whether qualified path in expression is in an error state. - inline bool is_error() const { - return path_type.is_error(); - } - - // Creates an error qualified path in expression. - static QualifiedPathInExpression create_error() { - return QualifiedPathInExpression( - QualifiedPathType::create_error(), ::std::vector<PathExprSegment>()); - } - - Location get_locus() const { - return locus; - } - - Location get_locus_slow() const OVERRIDE { - return get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual QualifiedPathInExpression* clone_pattern_impl() const OVERRIDE { - return new QualifiedPathInExpression(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual QualifiedPathInExpression* clone_expr_without_block_impl() const OVERRIDE { - return new QualifiedPathInExpression(*this); - } - }; - - // Represents a qualified path in a type; used for disambiguating trait function calls - class QualifiedPathInType : public TypeNoBounds { - QualifiedPathType path_type; - // ::std::vector<TypePathSegment> segments; - ::std::vector< ::std::unique_ptr<TypePathSegment> > segments; - - Location locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual QualifiedPathInType* clone_type_impl() const OVERRIDE { - return new QualifiedPathInType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual QualifiedPathInType* clone_type_no_bounds_impl() const OVERRIDE { - return new QualifiedPathInType(*this); - } - - public: - QualifiedPathInType(QualifiedPathType qual_path_type, - ::std::vector< ::std::unique_ptr<TypePathSegment> > path_segments, - Location locus = Location()) : - path_type(::std::move(qual_path_type)), - segments(::std::move(path_segments)), locus(locus) {} - - // TODO: maybe make a shortcut constructor that has QualifiedPathType elements as params - - // Copy constructor with vector clone - QualifiedPathInType(QualifiedPathInType const& other) : - path_type(other.path_type), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - segments.reserve(other.segments.size()); - - for (const auto& e : other.segments) { - segments.push_back(e->clone_type_path_segment()); - } - } - - // Overloaded assignment operator with vector clone - QualifiedPathInType& operator=(QualifiedPathInType const& other) { - path_type = other.path_type; - locus = other.locus; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - segments.reserve(other.segments.size()); - - for (const auto& e : other.segments) { - segments.push_back(e->clone_type_path_segment()); - } - - return *this; - } - - // move constructors - QualifiedPathInType(QualifiedPathInType&& other) = default; - QualifiedPathInType& operator=(QualifiedPathInType&& other) = default; - - // Returns whether qualified path in type is in an error state. - inline bool is_error() const { - return path_type.is_error(); - } - - // Creates an error state qualified path in type. - static QualifiedPathInType create_error() { - return QualifiedPathInType(QualifiedPathType::create_error(), - ::std::vector< ::std::unique_ptr<TypePathSegment> >()); - } - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - } -} +namespace AST { +// make intellisense calm +/*typedef ::std::string Symbol; +typedef int Lifetime; +typedef int Type; +typedef int Binding;*/ + +// The "identifier" (not generic args) aspect of each path expression segment +class PathIdentSegment +{ + ::std::string segment_name; + + // TODO: should this have location info stored? + + // only allow identifiers, "super", "self", "Self", "crate", or "$crate" +public: + PathIdentSegment (::std::string segment_name) + : segment_name (::std::move (segment_name)) + {} + + /* TODO: insert check in constructor for this? Or is this a semantic error + * best handled then? */ + + // TODO: does this require visitor. pretty sure this isn't polymorphic, but + // not entirely sure + + // Creates an error PathIdentSegment. + static PathIdentSegment create_error () { return PathIdentSegment (""); } + + // Returns whether PathIdentSegment is in an error state. + inline bool is_error () const { return segment_name.empty (); } + + ::std::string as_string () const { return segment_name; } +}; + +// A binding of an identifier to a type used in generic arguments in paths +struct GenericArgsBinding +{ +private: + Identifier identifier; + // Type type; + ::std::unique_ptr<Type> type; + + Location locus; + +public: + // Returns whether binding is in an error state. + inline bool is_error () const + { + return type + == NULL; // and also identifier is empty, but cheaper computation + } + + // Creates an error state generic args binding. + static GenericArgsBinding create_error () + { + return GenericArgsBinding ("", NULL); + } + + // Pointer type for type in constructor to enable polymorphism + GenericArgsBinding (Identifier ident, ::std::unique_ptr<Type> type_ptr, + Location locus = Location ()) + : identifier (::std::move (ident)), type (::std::move (type_ptr)), + locus (locus) + {} + + // Copy constructor has to deep copy the type as it is a unique pointer + GenericArgsBinding (GenericArgsBinding const &other) + : identifier (other.identifier), type (other.type->clone_type ()), + locus (other.locus) + {} + + // default destructor + ~GenericArgsBinding () = default; + + // Overload assignment operator to deep copy the pointed-to type + GenericArgsBinding &operator= (GenericArgsBinding const &other) + { + identifier = other.identifier; + type = other.type->clone_type (); + locus = other.locus; + return *this; + } + + // move constructors + GenericArgsBinding (GenericArgsBinding &&other) = default; + GenericArgsBinding &operator= (GenericArgsBinding &&other) = default; + + ::std::string as_string () const; +}; + +// Generic arguments allowed in each path expression segment - inline? +struct GenericArgs +{ + ::std::vector<Lifetime> lifetime_args; + //::std::vector<Type> type_args; + ::std::vector< ::std::unique_ptr<Type> > type_args; + ::std::vector<GenericArgsBinding> binding_args; + + Location locus; + +public: + // Returns true if there are any generic arguments + inline bool has_generic_args () const + { + return !(lifetime_args.empty () && type_args.empty () + && binding_args.empty ()); + } + + GenericArgs (::std::vector<Lifetime> lifetime_args, + ::std::vector< ::std::unique_ptr<Type> > type_args, + ::std::vector<GenericArgsBinding> binding_args, + Location locus = Location ()) + : lifetime_args (::std::move (lifetime_args)), + type_args (::std::move (type_args)), + binding_args (::std::move (binding_args)), locus (locus) + {} + + // copy constructor with vector clone + GenericArgs (GenericArgs const &other) + : lifetime_args (other.lifetime_args), binding_args (other.binding_args), + locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + type_args.reserve (other.type_args.size ()); + + for (const auto &e : other.type_args) + { + type_args.push_back (e->clone_type ()); + } + } + + ~GenericArgs () = default; + + // overloaded assignment operator to vector clone + GenericArgs &operator= (GenericArgs const &other) + { + lifetime_args = other.lifetime_args; + binding_args = other.binding_args; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + type_args.reserve (other.type_args.size ()); + + for (const auto &e : other.type_args) + { + type_args.push_back (e->clone_type ()); + } + + return *this; + } + + // move constructors + GenericArgs (GenericArgs &&other) = default; + GenericArgs &operator= (GenericArgs &&other) = default; + + // Creates an empty GenericArgs (no arguments) + static GenericArgs create_empty () + { + return GenericArgs (::std::vector<Lifetime> (), + ::std::vector< ::std::unique_ptr<Type> > (), + ::std::vector<GenericArgsBinding> ()); + } + + ::std::string as_string () const; +}; + +// A segment of a path in expression, including an identifier aspect and maybe +// generic args +class PathExprSegment +{ // or should this extend PathIdentSegment? +private: + PathIdentSegment segment_name; + + // bool has_generic_args; + GenericArgs generic_args; + + Location locus; + + // TODO: does this require visitor? pretty sure not polymorphic + +public: + // Returns true if there are any generic arguments + inline bool has_generic_args () const + { + return generic_args.has_generic_args (); + } + + // Constructor for segment (from IdentSegment and GenericArgs) + PathExprSegment (PathIdentSegment segment_name, Location locus = Location (), + GenericArgs generic_args = GenericArgs::create_empty ()) + : segment_name (::std::move (segment_name)), + generic_args (::std::move (generic_args)), locus (locus) + {} + + // Constructor for segment with generic arguments (from segment name and all + // args) + PathExprSegment (::std::string segment_name, Location locus, + ::std::vector<Lifetime> lifetime_args + = ::std::vector<Lifetime> (), + ::std::vector< ::std::unique_ptr<Type> > type_args + = ::std::vector< ::std::unique_ptr<Type> > (), + ::std::vector<GenericArgsBinding> binding_args + = ::std::vector<GenericArgsBinding> ()) + : segment_name (PathIdentSegment (::std::move (segment_name))), + generic_args (GenericArgs (::std::move (lifetime_args), + ::std::move (type_args), + ::std::move (binding_args))), + locus (locus) + {} + + // Returns whether path expression segment is in an error state. + inline bool is_error () const { return segment_name.is_error (); } + + // Creates an error-state path expression segment. + static PathExprSegment create_error () + { + return PathExprSegment (PathIdentSegment::create_error ()); + } + + ::std::string as_string () const; + + inline Location get_locus () const { return locus; } +}; + +// AST node representing a pattern that involves a "path" - abstract base class +class PathPattern : public Pattern +{ + ::std::vector<PathExprSegment> segments; + +protected: + PathPattern (::std::vector<PathExprSegment> segments) + : segments (::std::move (segments)) + {} + + // Returns whether path has segments. + inline bool has_segments () const { 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; + +public: + /* Returns whether the path is a single segment (excluding qualified path + * initial as segment). */ + inline bool is_single_segment () const { return segments.size () == 1; } + + virtual ::std::string as_string () const; +}; + +// AST node representing a path-in-expression pattern (path that allows generic +// arguments) +class PathInExpression : public PathPattern, public PathExpr +{ + bool has_opening_scope_resolution; + + Location locus; + +public: + ::std::string as_string () const; + + // Constructor + PathInExpression (::std::vector<PathExprSegment> path_segments, + Location locus = Location (), + bool has_opening_scope_resolution = false, + ::std::vector<Attribute> outer_attrs + = ::std::vector<Attribute> ()) + : PathPattern (::std::move (path_segments)), + PathExpr (::std::move (outer_attrs)), + has_opening_scope_resolution (has_opening_scope_resolution), locus (locus) + {} + + // Creates an error state path in expression. + static PathInExpression create_error () + { + return PathInExpression (::std::vector<PathExprSegment> ()); + } + + // Returns whether path in expression is in an error state. + inline bool is_error () const { return !has_segments (); } + + /* Converts PathInExpression to SimplePath if possible (i.e. no generic + * arguments). Otherwise returns an empty SimplePath. */ + inline SimplePath as_simple_path () const + { + /* delegate to parent class as can't access segments. however, + * QualifiedPathInExpression conversion to simple path wouldn't make sense, + * so the method in the parent class should be protected, not public. Have + * to pass in opening scope resolution as parent class has no access to it. + */ + return convert_to_simple_path (has_opening_scope_resolution); + } + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual PathInExpression *clone_pattern_impl () const OVERRIDE + { + return new PathInExpression (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual PathInExpression *clone_expr_without_block_impl () const OVERRIDE + { + return new PathInExpression (*this); + } +}; + +// Base class for segments used in type paths - not abstract (represents an +// ident-only segment) +class TypePathSegment +{ + /* TODO: may have to unify TypePathSegment and PathExprSegment (which are + * mostly the same anyway) in order to resolve goddamn syntax ambiguities. One + * difference is that function on TypePathSegment is not allowed if + * GenericArgs are, so could disallow that in constructor, which won't give + * that much size overhead. */ + PathIdentSegment ident_segment; + + Location locus; + +protected: + // This is protected because it is only really used by derived classes, not + // the base. + bool has_separating_scope_resolution; + + // Clone function implementation - not pure virtual as overrided by subclasses + virtual TypePathSegment *clone_type_path_segment_impl () const + { + return new TypePathSegment (*this); + } + +public: + virtual ~TypePathSegment () {} + + // Unique pointer custom clone function + ::std::unique_ptr<TypePathSegment> clone_type_path_segment () const + { + return ::std::unique_ptr<TypePathSegment> (clone_type_path_segment_impl ()); + } + + TypePathSegment (PathIdentSegment ident_segment, + bool has_separating_scope_resolution, Location locus) + : ident_segment (::std::move (ident_segment)), locus (locus), + has_separating_scope_resolution (has_separating_scope_resolution) + {} + + TypePathSegment (::std::string segment_name, + bool has_separating_scope_resolution, Location locus) + : ident_segment (PathIdentSegment (::std::move (segment_name))), + locus (locus), + has_separating_scope_resolution (has_separating_scope_resolution) + {} + + virtual ::std::string as_string () const + { + return ident_segment.as_string (); + } + + // Returns whether the type path segment is in an error state. May be virtual + // in future. + inline bool is_error () const { return ident_segment.is_error (); } + + /* Returns whether segment is identifier only (as opposed to generic args or + function). Overriden in derived classes with other segments. */ + virtual bool is_ident_only () const { return true; } + + inline Location get_locus () const { return locus; } + + // not pure virtual as class not abstract + virtual void accept_vis (ASTVisitor &vis); +}; + +// Segment used in type path with generic args +class TypePathSegmentGeneric : public TypePathSegment +{ + GenericArgs generic_args; + +public: + inline bool has_generic_args () const + { + return generic_args.has_generic_args (); + } + + bool is_ident_only () const { return false; } + + // Constructor with PathIdentSegment and GenericArgs + TypePathSegmentGeneric (PathIdentSegment ident_segment, + bool has_separating_scope_resolution, + GenericArgs generic_args, Location locus) + : TypePathSegment (::std::move (ident_segment), + has_separating_scope_resolution, locus), + generic_args (::std::move (generic_args)) + {} + + // Constructor from segment name and all args + TypePathSegmentGeneric (::std::string segment_name, + bool has_separating_scope_resolution, + ::std::vector<Lifetime> lifetime_args, + ::std::vector< ::std::unique_ptr<Type> > type_args, + ::std::vector<GenericArgsBinding> binding_args, + Location locus) + : TypePathSegment (::std::move (segment_name), + has_separating_scope_resolution, locus), + generic_args (GenericArgs (::std::move (lifetime_args), + ::std::move (type_args), + ::std::move (binding_args))) + {} + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to override base class method + virtual TypePathSegmentGeneric *clone_type_path_segment_impl () const OVERRIDE + { + return new TypePathSegmentGeneric (*this); + } +}; + +// A function as represented in a type path +struct TypePathFunction +{ +private: + // TODO: remove + /*bool has_inputs; + TypePathFnInputs inputs;*/ + //::std::vector<Type> inputs; // inlined from TypePathFnInputs + ::std::vector< ::std::unique_ptr<Type> > inputs; + + // bool has_type; + // Type type; + ::std::unique_ptr<Type> return_type; + + // FIXME: think of better way to mark as invalid than taking up storage + bool is_invalid; + + // TODO: should this have location info? + +protected: + // Constructor only used to create invalid type path functions. + TypePathFunction (bool is_invalid) : is_invalid (is_invalid) {} + +public: + // Returns whether the return type of the function has been specified. + inline bool has_return_type () const { return return_type != NULL; } + + // Returns whether the function has inputs. + inline bool has_inputs () const { return !inputs.empty (); } + + // Returns whether function is in an error state. + inline bool is_error () const { return is_invalid; } + + // Creates an error state function. + static TypePathFunction create_error () { return TypePathFunction (true); } + + // Constructor + TypePathFunction (::std::vector< ::std::unique_ptr<Type> > inputs, + Type *type = NULL) + : inputs (::std::move (inputs)), return_type (type), is_invalid (false) + {} + // FIXME: deprecated + + // Constructor + TypePathFunction (::std::vector< ::std::unique_ptr<Type> > inputs, + ::std::unique_ptr<Type> type = NULL) + : inputs (::std::move (inputs)), return_type (::std::move (type)), + is_invalid (false) + {} + + // Copy constructor with clone + TypePathFunction (TypePathFunction const &other) + : /*inputs(other.inputs),*/ return_type (other.return_type->clone_type ()), + is_invalid (other.is_invalid) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + inputs.reserve (other.inputs.size ()); + + for (const auto &e : other.inputs) + { + inputs.push_back (e->clone_type ()); + } + } + + ~TypePathFunction () = default; + + // Overloaded assignment operator to clone type + TypePathFunction &operator= (TypePathFunction const &other) + { + // inputs = other.inputs; + return_type = other.return_type->clone_type (); + is_invalid = other.is_invalid; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + inputs.reserve (other.inputs.size ()); + + for (const auto &e : other.inputs) + { + inputs.push_back (e->clone_type ()); + } + + return *this; + } + + // move constructors + TypePathFunction (TypePathFunction &&other) = default; + TypePathFunction &operator= (TypePathFunction &&other) = default; + + ::std::string as_string () const; +}; + +// Segment used in type path with a function argument +class TypePathSegmentFunction : public TypePathSegment +{ + TypePathFunction function_path; + +public: + // Constructor with PathIdentSegment and TypePathFn + TypePathSegmentFunction (PathIdentSegment ident_segment, + bool has_separating_scope_resolution, + TypePathFunction function_path, Location locus) + : TypePathSegment (::std::move (ident_segment), + has_separating_scope_resolution, locus), + function_path (::std::move (function_path)) + {} + + // Constructor with segment name and TypePathFn + TypePathSegmentFunction (::std::string segment_name, + bool has_separating_scope_resolution, + TypePathFunction function_path, Location locus) + : TypePathSegment (::std::move (segment_name), + has_separating_scope_resolution, locus), + function_path (::std::move (function_path)) + {} + + ::std::string as_string () const; + + bool is_ident_only () const { return false; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to override base class method + virtual TypePathSegmentFunction * + clone_type_path_segment_impl () const OVERRIDE + { + return new TypePathSegmentFunction (*this); + } +}; + +// Path used inside types +class TypePath : public TypeNoBounds +{ + bool has_opening_scope_resolution; + ::std::vector< ::std::unique_ptr<TypePathSegment> > segments; + + Location locus; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TypePath *clone_type_impl () const OVERRIDE + { + return new TypePath (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual TypePath *clone_type_no_bounds_impl () const OVERRIDE + { + return new TypePath (*this); + } + +public: + /* Returns whether the TypePath has an opening scope resolution operator (i.e. + * is global path or crate-relative path, not module-relative) */ + inline bool has_opening_scope_resolution_op () const + { + return has_opening_scope_resolution; + } + + // Returns whether the TypePath is in an invalid state. + inline bool is_error () const { return segments.empty (); } + + // Creates an error state TypePath. + static TypePath create_error () + { + return TypePath (::std::vector< ::std::unique_ptr<TypePathSegment> > (), + Location ()); + } + + // Constructor + TypePath (::std::vector< ::std::unique_ptr<TypePathSegment> > segments, + Location locus, bool has_opening_scope_resolution = false) + : has_opening_scope_resolution (has_opening_scope_resolution), + segments (::std::move (segments)), locus (locus) + {} + + // Copy constructor with vector clone + TypePath (TypePath const &other) + : has_opening_scope_resolution (other.has_opening_scope_resolution), + locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + segments.reserve (other.segments.size ()); + + for (const auto &e : other.segments) + { + segments.push_back (e->clone_type_path_segment ()); + } + } + + // Overloaded assignment operator with clone + TypePath &operator= (TypePath const &other) + { + has_opening_scope_resolution = other.has_opening_scope_resolution; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + segments.reserve (other.segments.size ()); + + for (const auto &e : other.segments) + { + segments.push_back (e->clone_type_path_segment ()); + } + + return *this; + } + + // move constructors + TypePath (TypePath &&other) = default; + TypePath &operator= (TypePath &&other) = default; + + ::std::string as_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; + + // Creates a trait bound with a clone of this type path as its only element. + virtual TraitBound *to_trait_bound (bool in_parens) const OVERRIDE; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; +}; + +struct QualifiedPathType +{ +private: + // Type type_to_invoke_on; + ::std::unique_ptr<Type> type_to_invoke_on; + + // bool has_as_clause; + TypePath trait_path; + + Location locus; + +public: + // Constructor + QualifiedPathType (::std::unique_ptr<Type> invoke_on_type, + Location locus = Location (), + TypePath trait_path = TypePath::create_error ()) + : type_to_invoke_on (::std::move (invoke_on_type)), + trait_path (::std::move (trait_path)), locus (locus) + {} + + // Copy constructor uses custom deep copy for Type to preserve polymorphism + QualifiedPathType (QualifiedPathType const &other) + : type_to_invoke_on (other.type_to_invoke_on->clone_type ()), + trait_path (other.trait_path), locus (other.locus) + {} + + // default destructor + ~QualifiedPathType () = default; + + // overload assignment operator to use custom clone method + QualifiedPathType &operator= (QualifiedPathType const &other) + { + type_to_invoke_on = other.type_to_invoke_on->clone_type (); + trait_path = other.trait_path; + locus = other.locus; + return *this; + } + + // move constructor + QualifiedPathType (QualifiedPathType &&other) = default; + QualifiedPathType &operator= (QualifiedPathType &&other) = default; + + // Returns whether the qualified path type has a rebind as clause. + inline bool has_as_clause () const { return !trait_path.is_error (); } + + // Returns whether the qualified path type is in an error state. + inline bool is_error () const { return type_to_invoke_on == NULL; } + + // Creates an error state qualified path type. + static QualifiedPathType create_error () { return QualifiedPathType (NULL); } + + ::std::string as_string () const; + + inline Location get_locus () const { return locus; } +}; + +/* AST node representing a qualified path-in-expression pattern (path that + * allows specifying trait functions) */ +class QualifiedPathInExpression : public PathPattern, public PathExpr +{ + QualifiedPathType path_type; + + Location locus; + +public: + ::std::string as_string () const; + + QualifiedPathInExpression (QualifiedPathType qual_path_type, + ::std::vector<PathExprSegment> path_segments, + Location locus = Location (), + ::std::vector<Attribute> outer_attrs + = ::std::vector<Attribute> ()) + : PathPattern (::std::move (path_segments)), + PathExpr (::std::move (outer_attrs)), + path_type (::std::move (qual_path_type)), locus (locus) + {} + + // TODO: maybe make a shortcut constructor that has QualifiedPathType elements + // as params + + // Copy constructor, destructor, and assignment operator overload shouldn't be + // required + + // Returns whether qualified path in expression is in an error state. + inline bool is_error () const { return path_type.is_error (); } + + // Creates an error qualified path in expression. + static QualifiedPathInExpression create_error () + { + return QualifiedPathInExpression (QualifiedPathType::create_error (), + ::std::vector<PathExprSegment> ()); + } + + Location get_locus () const { return locus; } + + Location get_locus_slow () const OVERRIDE { return get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual QualifiedPathInExpression *clone_pattern_impl () const OVERRIDE + { + return new QualifiedPathInExpression (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual QualifiedPathInExpression * + clone_expr_without_block_impl () const OVERRIDE + { + return new QualifiedPathInExpression (*this); + } +}; + +// Represents a qualified path in a type; used for disambiguating trait function +// calls +class QualifiedPathInType : public TypeNoBounds +{ + QualifiedPathType path_type; + // ::std::vector<TypePathSegment> segments; + ::std::vector< ::std::unique_ptr<TypePathSegment> > segments; + + Location locus; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual QualifiedPathInType *clone_type_impl () const OVERRIDE + { + return new QualifiedPathInType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual QualifiedPathInType *clone_type_no_bounds_impl () const OVERRIDE + { + return new QualifiedPathInType (*this); + } + +public: + QualifiedPathInType ( + QualifiedPathType qual_path_type, + ::std::vector< ::std::unique_ptr<TypePathSegment> > path_segments, + Location locus = Location ()) + : path_type (::std::move (qual_path_type)), + segments (::std::move (path_segments)), locus (locus) + {} + + // TODO: maybe make a shortcut constructor that has QualifiedPathType elements + // as params + + // Copy constructor with vector clone + QualifiedPathInType (QualifiedPathInType const &other) + : path_type (other.path_type), locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + segments.reserve (other.segments.size ()); + + for (const auto &e : other.segments) + { + segments.push_back (e->clone_type_path_segment ()); + } + } + + // Overloaded assignment operator with vector clone + QualifiedPathInType &operator= (QualifiedPathInType const &other) + { + path_type = other.path_type; + locus = other.locus; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + segments.reserve (other.segments.size ()); + + for (const auto &e : other.segments) + { + segments.push_back (e->clone_type_path_segment ()); + } + + return *this; + } + + // move constructors + QualifiedPathInType (QualifiedPathInType &&other) = default; + QualifiedPathInType &operator= (QualifiedPathInType &&other) = default; + + // Returns whether qualified path in type is in an error state. + inline bool is_error () const { return path_type.is_error (); } + + // Creates an error state qualified path in type. + static QualifiedPathInType create_error () + { + return QualifiedPathInType ( + QualifiedPathType::create_error (), + ::std::vector< ::std::unique_ptr<TypePathSegment> > ()); + } + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; +}; +} // namespace AST +} // namespace Rust #endif diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 5df0528..533a65f 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -4,1160 +4,1320 @@ #include "rust-ast.h" namespace Rust { - namespace AST { - // Literal pattern AST node (comparing to a literal) - class LiteralPattern : public Pattern { - Literal lit; // make literal have a type given by enum, etc. rustc uses an extended form - // of its literal token implementation - // FIXME: literal representation - use LiteralExpr? or another thing? - - // Minus prefixed to literal (if integer or floating-point) - bool has_minus; - // Actually, this might be a good place to use a template. - - Location locus; - - public: - ::std::string as_string() const; - - // Constructor for a literal pattern - LiteralPattern(Literal lit, Location locus, bool has_minus = false) : - lit(::std::move(lit)), has_minus(has_minus), locus(locus) {} - - LiteralPattern( - ::std::string val, Literal::LitType type, Location locus, bool has_minus = false) : - lit(Literal(::std::move(val), type)), - has_minus(has_minus), locus(locus) {} - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LiteralPattern* clone_pattern_impl() const OVERRIDE { - return new LiteralPattern(*this); - } - }; - - // Identifier pattern AST node (bind value matched to a variable) - class IdentifierPattern : public Pattern { - Identifier variable_ident; - bool is_ref; - bool is_mut; - - // bool has_pattern; - // Pattern* to_bind; - ::std::unique_ptr<Pattern> to_bind; - - Location locus; - - public: - /*~IdentifierPattern() { - delete to_bind; - }*/ - - ::std::string as_string() const; - - // Returns whether the IdentifierPattern has a pattern to bind. - inline bool has_pattern_to_bind() const { - return to_bind != NULL; - } - - // Constructor - IdentifierPattern(Identifier ident, Location locus, bool is_ref = false, - bool is_mut = false, ::std::unique_ptr<Pattern> to_bind = NULL) : - variable_ident(::std::move(ident)), - is_ref(is_ref), is_mut(is_mut), to_bind(::std::move(to_bind)), locus(locus) {} - - // Copy constructor with clone - IdentifierPattern(IdentifierPattern const& other) : - variable_ident(other.variable_ident), is_ref(other.is_ref), is_mut(other.is_mut), - locus(other.locus) { - // fix to get prevent null pointer dereference - if (other.to_bind != NULL) { - to_bind = other.to_bind->clone_pattern(); - } - } - - // Destructor - define here if required - - // Overload assignment operator to use clone - IdentifierPattern& operator=(IdentifierPattern const& other) { - variable_ident = other.variable_ident; - is_ref = other.is_ref; - is_mut = other.is_mut; - locus = other.locus; - // fix to get prevent null pointer dereference - if (other.to_bind != NULL) { - to_bind = other.to_bind->clone_pattern(); - } - - return *this; - } - - // default move semantics - IdentifierPattern(IdentifierPattern&& other) = default; - IdentifierPattern& operator=(IdentifierPattern&& other) = default; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual IdentifierPattern* clone_pattern_impl() const OVERRIDE { - return new IdentifierPattern(*this); - } - }; - - // AST node for using the '_' wildcard "match any value" pattern - class WildcardPattern : public Pattern { - Location locus; - - public: - ::std::string as_string() const { - return ::std::string(1, '_'); - } - - WildcardPattern(Location locus) : locus(locus) {} - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual WildcardPattern* clone_pattern_impl() const OVERRIDE { - return new WildcardPattern(*this); - } - }; - - // Base range pattern bound (lower or upper limit) - abstract - class RangePatternBound { - /*union { - CharLiteral char_lit; - ByteLiteral byte_lit; - IntLiteral int_lit; - FloatLiteral float_lit; - PathInExpression path; - QualifiedPathInExpression qual_path; - } pattern;*/ - public: - virtual ~RangePatternBound() {} - - // Unique pointer custom clone function - ::std::unique_ptr<RangePatternBound> clone_range_pattern_bound() const { - return ::std::unique_ptr<RangePatternBound>(clone_range_pattern_bound_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual as RangePatternBound is abstract - virtual RangePatternBound* clone_range_pattern_bound_impl() const = 0; - }; - - // Literal-based pattern bound - class RangePatternBoundLiteral : public RangePatternBound { - Literal literal; - // Can only be a char, byte, int, or float literal - same impl here as previously - - // Minus prefixed to literal (if integer or floating-point) - bool has_minus; - - Location locus; - - public: - // Constructor - RangePatternBoundLiteral(Literal literal, Location locus, bool has_minus = false) : - literal(literal), has_minus(has_minus), locus(locus) {} - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangePatternBoundLiteral* clone_range_pattern_bound_impl() const OVERRIDE { - return new RangePatternBoundLiteral(*this); - } - }; - - // Path-based pattern bound - class RangePatternBoundPath : public RangePatternBound { - PathInExpression path; - - // TODO: should this be refactored so that PathInExpression is a subclass of - // RangePatternBound? - - public: - RangePatternBoundPath(PathInExpression path) : path(::std::move(path)) {} - - ::std::string as_string() const { - return path.as_string(); - } - - Location get_locus() const { - return path.get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangePatternBoundPath* clone_range_pattern_bound_impl() const OVERRIDE { - return new RangePatternBoundPath(*this); - } - }; - - // Qualified path-based pattern bound - class RangePatternBoundQualPath : public RangePatternBound { - QualifiedPathInExpression path; - - /* TODO: should this be refactored so that QualifiedPathInExpression is a subclass of - * RangePatternBound? */ - - public: - RangePatternBoundQualPath(QualifiedPathInExpression path) : path(::std::move(path)) {} - - ::std::string as_string() const { - return path.as_string(); - } - - Location get_locus() const { - return path.get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangePatternBoundQualPath* clone_range_pattern_bound_impl() const OVERRIDE { - return new RangePatternBoundQualPath(*this); - } - }; +namespace AST { +// Literal pattern AST node (comparing to a literal) +class LiteralPattern : public Pattern +{ + Literal lit; // make literal have a type given by enum, etc. rustc uses an + // extended form + // of its literal token implementation + // FIXME: literal representation - use LiteralExpr? or another thing? + + // Minus prefixed to literal (if integer or floating-point) + bool has_minus; + // Actually, this might be a good place to use a template. + + Location locus; + +public: + ::std::string as_string () const; + + // Constructor for a literal pattern + LiteralPattern (Literal lit, Location locus, bool has_minus = false) + : lit (::std::move (lit)), has_minus (has_minus), locus (locus) + {} + + LiteralPattern (::std::string val, Literal::LitType type, Location locus, + bool has_minus = false) + : lit (Literal (::std::move (val), type)), has_minus (has_minus), + locus (locus) + {} + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual LiteralPattern *clone_pattern_impl () const OVERRIDE + { + return new LiteralPattern (*this); + } +}; + +// Identifier pattern AST node (bind value matched to a variable) +class IdentifierPattern : public Pattern +{ + Identifier variable_ident; + bool is_ref; + bool is_mut; + + // bool has_pattern; + // Pattern* to_bind; + ::std::unique_ptr<Pattern> to_bind; + + Location locus; + +public: + /*~IdentifierPattern() { + delete to_bind; + }*/ + + ::std::string as_string () const; + + // Returns whether the IdentifierPattern has a pattern to bind. + inline bool has_pattern_to_bind () const { return to_bind != NULL; } + + // Constructor + IdentifierPattern (Identifier ident, Location locus, bool is_ref = false, + bool is_mut = false, + ::std::unique_ptr<Pattern> to_bind = NULL) + : variable_ident (::std::move (ident)), is_ref (is_ref), is_mut (is_mut), + to_bind (::std::move (to_bind)), locus (locus) + {} + + // Copy constructor with clone + IdentifierPattern (IdentifierPattern const &other) + : variable_ident (other.variable_ident), is_ref (other.is_ref), + is_mut (other.is_mut), locus (other.locus) + { + // fix to get prevent null pointer dereference + if (other.to_bind != NULL) + { + to_bind = other.to_bind->clone_pattern (); + } + } + + // Destructor - define here if required + + // Overload assignment operator to use clone + IdentifierPattern &operator= (IdentifierPattern const &other) + { + variable_ident = other.variable_ident; + is_ref = other.is_ref; + is_mut = other.is_mut; + locus = other.locus; + // fix to get prevent null pointer dereference + if (other.to_bind != NULL) + { + to_bind = other.to_bind->clone_pattern (); + } + + return *this; + } + + // default move semantics + IdentifierPattern (IdentifierPattern &&other) = default; + IdentifierPattern &operator= (IdentifierPattern &&other) = default; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual IdentifierPattern *clone_pattern_impl () const OVERRIDE + { + return new IdentifierPattern (*this); + } +}; + +// AST node for using the '_' wildcard "match any value" pattern +class WildcardPattern : public Pattern +{ + Location locus; + +public: + ::std::string as_string () const { return ::std::string (1, '_'); } + + WildcardPattern (Location locus) : locus (locus) {} + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual WildcardPattern *clone_pattern_impl () const OVERRIDE + { + return new WildcardPattern (*this); + } +}; + +// Base range pattern bound (lower or upper limit) - abstract +class RangePatternBound +{ + /*union { + CharLiteral char_lit; + ByteLiteral byte_lit; + IntLiteral int_lit; + FloatLiteral float_lit; + PathInExpression path; + QualifiedPathInExpression qual_path; + } pattern;*/ +public: + virtual ~RangePatternBound () {} + + // Unique pointer custom clone function + ::std::unique_ptr<RangePatternBound> clone_range_pattern_bound () const + { + return ::std::unique_ptr<RangePatternBound> ( + clone_range_pattern_bound_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // pure virtual as RangePatternBound is abstract + virtual RangePatternBound *clone_range_pattern_bound_impl () const = 0; +}; + +// Literal-based pattern bound +class RangePatternBoundLiteral : public RangePatternBound +{ + Literal literal; + // Can only be a char, byte, int, or float literal - same impl here as + // previously + + // Minus prefixed to literal (if integer or floating-point) + bool has_minus; + + Location locus; + +public: + // Constructor + RangePatternBoundLiteral (Literal literal, Location locus, + bool has_minus = false) + : literal (literal), has_minus (has_minus), locus (locus) + {} + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangePatternBoundLiteral * + clone_range_pattern_bound_impl () const OVERRIDE + { + return new RangePatternBoundLiteral (*this); + } +}; + +// Path-based pattern bound +class RangePatternBoundPath : public RangePatternBound +{ + PathInExpression path; + + // TODO: should this be refactored so that PathInExpression is a subclass of + // RangePatternBound? + +public: + RangePatternBoundPath (PathInExpression path) : path (::std::move (path)) {} + + ::std::string as_string () const { return path.as_string (); } + + Location get_locus () const { return path.get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangePatternBoundPath * + clone_range_pattern_bound_impl () const OVERRIDE + { + return new RangePatternBoundPath (*this); + } +}; + +// Qualified path-based pattern bound +class RangePatternBoundQualPath : public RangePatternBound +{ + QualifiedPathInExpression path; + + /* TODO: should this be refactored so that QualifiedPathInExpression is a + * subclass of RangePatternBound? */ + +public: + RangePatternBoundQualPath (QualifiedPathInExpression path) + : path (::std::move (path)) + {} + + ::std::string as_string () const { return path.as_string (); } + + Location get_locus () const { return path.get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangePatternBoundQualPath * + clone_range_pattern_bound_impl () const OVERRIDE + { + return new RangePatternBoundQualPath (*this); + } +}; + +// AST node for matching within a certain range (range pattern) +class RangePattern : public Pattern +{ + /*RangePatternBound lower; + RangePatternBound upper;*/ + ::std::unique_ptr<RangePatternBound> lower; + ::std::unique_ptr<RangePatternBound> upper; + + bool has_ellipsis_syntax; + + // location only stored to avoid a dereference - lower pattern should give + // correct location so maybe change in future + Location locus; + +public: + ::std::string as_string () const; + + // Constructor + RangePattern (::std::unique_ptr<RangePatternBound> lower, + ::std::unique_ptr<RangePatternBound> upper, Location locus, + bool has_ellipsis_syntax = false) + : lower (::std::move (lower)), upper (::std::move (upper)), + has_ellipsis_syntax (has_ellipsis_syntax), locus (locus) + {} + + // 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) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + RangePattern &operator= (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; + + return *this; + } + + // default move semantics + RangePattern (RangePattern &&other) = default; + RangePattern &operator= (RangePattern &&other) = default; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RangePattern *clone_pattern_impl () const OVERRIDE + { + return new RangePattern (*this); + } +}; + +// AST node for pattern based on dereferencing the pointers given +class ReferencePattern : public Pattern +{ + bool has_two_amps; + bool is_mut; + // Pattern* pattern; + ::std::unique_ptr<Pattern> pattern; + + Location locus; + +public: + /*~ReferencePattern() { + delete pattern; + }*/ + + ::std::string as_string () const; + + ReferencePattern (::std::unique_ptr<Pattern> pattern, bool is_mut_reference, + bool ref_has_two_amps, Location locus) + : has_two_amps (ref_has_two_amps), is_mut (is_mut_reference), + pattern (::std::move (pattern)), locus (locus) + {} + + // Copy constructor requires clone + ReferencePattern (ReferencePattern const &other) + : has_two_amps (other.has_two_amps), is_mut (other.is_mut), + pattern (other.pattern->clone_pattern ()), locus (other.locus) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone + ReferencePattern &operator= (ReferencePattern const &other) + { + pattern = other.pattern->clone_pattern (); + is_mut = other.is_mut; + has_two_amps = other.has_two_amps; + locus = other.locus; + + return *this; + } + + // default move semantics + ReferencePattern (ReferencePattern &&other) = default; + ReferencePattern &operator= (ReferencePattern &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ReferencePattern *clone_pattern_impl () const OVERRIDE + { + return new ReferencePattern (*this); + } +}; + +// aka StructPatternEtCetera; potential element in struct pattern +struct StructPatternEtc +{ +private: + ::std::vector<Attribute> outer_attrs; + + // should this store location data? + +public: + StructPatternEtc (::std::vector<Attribute> outer_attribs) + : outer_attrs (::std::move (outer_attribs)) + {} + + // Creates an empty StructPatternEtc + static StructPatternEtc create_empty () + { + return StructPatternEtc (::std::vector<Attribute> ()); + } +}; + +// Base class for a single field in a struct pattern - abstract +class StructPatternField +{ + ::std::vector<Attribute> outer_attrs; + /*union { + struct { + //TupleIndex index; + Pattern tuple_pattern; + } tuple_pattern; + struct { + //Identifier ident; + Pattern ident_pattern; + } ident_pattern; + struct { + bool has_ref; + bool has_mut; + //Identifier ident; + } ident; + } pattern;*/ + + Location locus; + +public: + virtual ~StructPatternField () {} + + // Unique pointer custom clone function + ::std::unique_ptr<StructPatternField> clone_struct_pattern_field () const + { + return ::std::unique_ptr<StructPatternField> ( + clone_struct_pattern_field_impl ()); + } + + virtual ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + StructPatternField (::std::vector<Attribute> outer_attribs, Location locus) + : outer_attrs (::std::move (outer_attribs)), locus (locus) + {} + + // Clone function implementation as pure virtual method + virtual StructPatternField *clone_struct_pattern_field_impl () const = 0; +}; + +// Tuple pattern single field in a struct pattern +class StructPatternFieldTuplePat : public StructPatternField +{ + TupleIndex index; + // Pattern* tuple_pattern; + ::std::unique_ptr<Pattern> tuple_pattern; + +public: + /*~StructPatternFieldTuplePat() { + delete tuple_pattern; + }*/ + + StructPatternFieldTuplePat (TupleIndex index, + ::std::unique_ptr<Pattern> tuple_pattern, + ::std::vector<Attribute> outer_attribs, + Location locus) + : StructPatternField (::std::move (outer_attribs), locus), index (index), + tuple_pattern (::std::move (tuple_pattern)) + {} + + // Copy constructor requires clone + StructPatternFieldTuplePat (StructPatternFieldTuplePat const &other) + : StructPatternField (other), index (other.index), + tuple_pattern (other.tuple_pattern->clone_pattern ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to perform clone + StructPatternFieldTuplePat & + operator= (StructPatternFieldTuplePat const &other) + { + StructPatternField::operator= (other); + tuple_pattern = other.tuple_pattern->clone_pattern (); + index = other.index; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // default move semantics + StructPatternFieldTuplePat (StructPatternFieldTuplePat &&other) = default; + StructPatternFieldTuplePat &operator= (StructPatternFieldTuplePat &&other) + = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructPatternFieldTuplePat * + clone_struct_pattern_field_impl () const OVERRIDE + { + return new StructPatternFieldTuplePat (*this); + } +}; + +// Identifier pattern single field in a struct pattern +class StructPatternFieldIdentPat : public StructPatternField +{ + Identifier ident; + // Pattern* ident_pattern; + ::std::unique_ptr<Pattern> ident_pattern; + +public: + /*~StructPatternFieldIdentPat() { + delete ident_pattern; + }*/ + + StructPatternFieldIdentPat (Identifier ident, + ::std::unique_ptr<Pattern> ident_pattern, + ::std::vector<Attribute> outer_attrs, + Location locus) + : StructPatternField (::std::move (outer_attrs), locus), + ident (::std::move (ident)), ident_pattern (::std::move (ident_pattern)) + {} + + // Copy constructor requires clone + StructPatternFieldIdentPat (StructPatternFieldIdentPat const &other) + : StructPatternField (other), ident (other.ident), + ident_pattern (other.ident_pattern->clone_pattern ()) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone + StructPatternFieldIdentPat & + operator= (StructPatternFieldIdentPat const &other) + { + StructPatternField::operator= (other); + ident = other.ident; + ident_pattern = other.ident_pattern->clone_pattern (); + // outer_attrs = other.outer_attrs; + + return *this; + } + + // default move semantics + StructPatternFieldIdentPat (StructPatternFieldIdentPat &&other) = default; + StructPatternFieldIdentPat &operator= (StructPatternFieldIdentPat &&other) + = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructPatternFieldIdentPat * + clone_struct_pattern_field_impl () const OVERRIDE + { + return new StructPatternFieldIdentPat (*this); + } +}; + +// Identifier only (with no pattern) single field in a struct pattern +class StructPatternFieldIdent : public StructPatternField +{ + bool has_ref; + bool has_mut; + + Identifier ident; + +public: + StructPatternFieldIdent (Identifier ident, bool is_ref, bool is_mut, + ::std::vector<Attribute> outer_attrs, Location locus) + : StructPatternField (::std::move (outer_attrs), locus), has_ref (is_ref), + has_mut (is_mut), ident (::std::move (ident)) + {} + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructPatternFieldIdent * + clone_struct_pattern_field_impl () const OVERRIDE + { + return new StructPatternFieldIdent (*this); + } +}; + +// Elements of a struct pattern +struct StructPatternElements +{ +private: + // bool has_struct_pattern_fields; + //::std::vector<StructPatternField> fields; + ::std::vector< ::std::unique_ptr<StructPatternField> > fields; + + bool has_struct_pattern_etc; + StructPatternEtc etc; + + // must have at least one of the two and maybe both + + // should this store location data? + +public: + // Returns whether there are any struct pattern fields + inline bool has_struct_pattern_fields () const { return !fields.empty (); } + + // Returns whether the struct pattern elements is entirely empty (no fields, + // no etc). + inline bool is_empty () const + { + return !has_struct_pattern_fields () && !has_struct_pattern_etc; + } + + // Constructor for StructPatternElements with both (potentially) + StructPatternElements ( + ::std::vector< ::std::unique_ptr<StructPatternField> > fields, + StructPatternEtc etc) + : fields (::std::move (fields)), has_struct_pattern_etc (true), + etc (::std::move (etc)) + {} + + // Constructor for StructPatternElements with no StructPatternEtc + StructPatternElements ( + ::std::vector< ::std::unique_ptr<StructPatternField> > fields) + : fields (::std::move (fields)), has_struct_pattern_etc (false), + etc (StructPatternEtc::create_empty ()) + {} + + // Copy constructor with vector clone + StructPatternElements (StructPatternElements const &other) + : has_struct_pattern_etc (other.has_struct_pattern_etc), etc (other.etc) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + fields.reserve (other.fields.size ()); + + for (const auto &e : other.fields) + { + fields.push_back (e->clone_struct_pattern_field ()); + } + } + + // Overloaded assignment operator with vector clone + StructPatternElements &operator= (StructPatternElements const &other) + { + etc = other.etc; + has_struct_pattern_etc = other.has_struct_pattern_etc; + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + fields.reserve (other.fields.size ()); + + for (const auto &e : other.fields) + { + fields.push_back (e->clone_struct_pattern_field ()); + } + + return *this; + } + + // move constructors + StructPatternElements (StructPatternElements &&other) = default; + StructPatternElements &operator= (StructPatternElements &&other) = default; + + // Creates an empty StructPatternElements + static StructPatternElements create_empty () + { + return StructPatternElements ( + ::std::vector< ::std::unique_ptr<StructPatternField> > ()); + } + + ::std::string as_string () const; +}; + +// Struct pattern AST node representation +class StructPattern : public Pattern +{ + PathInExpression path; + + // bool has_struct_pattern_elements; + StructPatternElements elems; + + // TODO: should this store location data? Accessor uses path location data. + +public: + ::std::string as_string () const; + + // Constructs a struct pattern from specified StructPatternElements + StructPattern (PathInExpression struct_path, + StructPatternElements elems + = StructPatternElements::create_empty ()) + : path (::std::move (struct_path)), elems (::std::move (elems)) + {} + + // TODO: constructor to construct via elements included in + // StructPatternElements + + // Returns whether struct pattern has any struct pattern elements (if not, it + // is empty). + inline bool has_struct_pattern_elems () const { return !elems.is_empty (); } + + Location get_locus () const { return path.get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual StructPattern *clone_pattern_impl () const OVERRIDE + { + return new StructPattern (*this); + } +}; + +// Base abstract class for patterns used in TupleStructPattern +class TupleStructItems +{ +public: + virtual ~TupleStructItems () {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + ::std::unique_ptr<TupleStructItems> clone_tuple_struct_items () const + { + return ::std::unique_ptr<TupleStructItems> ( + clone_tuple_struct_items_impl ()); + } + + virtual ::std::string as_string () const = 0; + + virtual void accept_vis (ASTVisitor &vis) = 0; + +protected: + // pure virtual clone implementation + virtual TupleStructItems *clone_tuple_struct_items_impl () const = 0; +}; + +// Class for non-ranged tuple struct pattern patterns +class TupleStructItemsNoRange : public TupleStructItems +{ + //::std::vector<Pattern> patterns; + ::std::vector< ::std::unique_ptr<Pattern> > patterns; + +public: + TupleStructItemsNoRange (::std::vector< ::std::unique_ptr<Pattern> > patterns) + : patterns (::std::move (patterns)) + {} + + // Copy constructor with vector clone + TupleStructItemsNoRange (TupleStructItemsNoRange const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + patterns.reserve (other.patterns.size ()); + + for (const auto &e : other.patterns) + { + patterns.push_back (e->clone_pattern ()); + } + } + + // Overloaded assignment operator with vector clone + TupleStructItemsNoRange &operator= (TupleStructItemsNoRange const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + patterns.reserve (other.patterns.size ()); + + for (const auto &e : other.patterns) + { + patterns.push_back (e->clone_pattern ()); + } + + return *this; + } + + // move constructors + TupleStructItemsNoRange (TupleStructItemsNoRange &&other) = default; + TupleStructItemsNoRange &operator= (TupleStructItemsNoRange &&other) + = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TupleStructItemsNoRange * + clone_tuple_struct_items_impl () const OVERRIDE + { + return new TupleStructItemsNoRange (*this); + } +}; + +// Class for ranged tuple struct pattern patterns +class TupleStructItemsRange : public TupleStructItems +{ + /*::std::vector<Pattern> lower_patterns; + ::std::vector<Pattern> upper_patterns;*/ + ::std::vector< ::std::unique_ptr<Pattern> > lower_patterns; + ::std::vector< ::std::unique_ptr<Pattern> > upper_patterns; + +public: + TupleStructItemsRange ( + ::std::vector< ::std::unique_ptr<Pattern> > lower_patterns, + ::std::vector< ::std::unique_ptr<Pattern> > upper_patterns) + : lower_patterns (::std::move (lower_patterns)), + upper_patterns (::std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + TupleStructItemsRange (TupleStructItemsRange const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + lower_patterns.reserve (other.lower_patterns.size ()); + + for (const auto &e : other.lower_patterns) + { + lower_patterns.push_back (e->clone_pattern ()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + upper_patterns.reserve (other.upper_patterns.size ()); + + for (const auto &e : other.upper_patterns) + { + upper_patterns.push_back (e->clone_pattern ()); + } + } + + // Overloaded assignment operator to clone + TupleStructItemsRange &operator= (TupleStructItemsRange const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + lower_patterns.reserve (other.lower_patterns.size ()); + + for (const auto &e : other.lower_patterns) + { + lower_patterns.push_back (e->clone_pattern ()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + upper_patterns.reserve (other.upper_patterns.size ()); + + for (const auto &e : other.upper_patterns) + { + upper_patterns.push_back (e->clone_pattern ()); + } + + return *this; + } + + // move constructors + TupleStructItemsRange (TupleStructItemsRange &&other) = default; + TupleStructItemsRange &operator= (TupleStructItemsRange &&other) = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TupleStructItemsRange *clone_tuple_struct_items_impl () const OVERRIDE + { + return new TupleStructItemsRange (*this); + } +}; + +// AST node representing a tuple struct pattern +class TupleStructPattern : public Pattern +{ + PathInExpression path; + // TupleStructItems items; + ::std::unique_ptr<TupleStructItems> items; + + // TOOD: should this store location data? current accessor uses path location + // data + +public: + ::std::string as_string () const; + + TupleStructPattern (PathInExpression tuple_struct_path, + ::std::unique_ptr<TupleStructItems> items) + : path (::std::move (tuple_struct_path)), items (::std::move (items)) + {} + + // Copy constructor required to clone + TupleStructPattern (TupleStructPattern const &other) + : path (other.path), items (other.items->clone_tuple_struct_items ()) + {} + + // Destructor - define here if required + + // Operator overload assignment operator to clone + TupleStructPattern &operator= (TupleStructPattern const &other) + { + path = other.path; + items = other.items->clone_tuple_struct_items (); + + return *this; + } + + // move constructors + TupleStructPattern (TupleStructPattern &&other) = default; + TupleStructPattern &operator= (TupleStructPattern &&other) = default; + + Location get_locus () const { return path.get_locus (); } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TupleStructPattern *clone_pattern_impl () const OVERRIDE + { + return new TupleStructPattern (*this); + } +}; + +// Base abstract class representing TuplePattern patterns +class TuplePatternItems +{ +public: + virtual ~TuplePatternItems () {} + + // TODO: should this store location data? + + // Unique pointer custom clone function + ::std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items () const + { + return ::std::unique_ptr<TuplePatternItems> ( + clone_tuple_pattern_items_impl ()); + } - // AST node for matching within a certain range (range pattern) - class RangePattern : public Pattern { - /*RangePatternBound lower; - RangePatternBound upper;*/ - ::std::unique_ptr<RangePatternBound> lower; - ::std::unique_ptr<RangePatternBound> upper; + virtual ::std::string as_string () const = 0; - bool has_ellipsis_syntax; + virtual void accept_vis (ASTVisitor &vis) = 0; - // location only stored to avoid a dereference - lower pattern should give correct - // location so maybe change in future - Location locus; - - public: - ::std::string as_string() const; +protected: + // pure virtual clone implementation + virtual TuplePatternItems *clone_tuple_pattern_items_impl () const = 0; +}; - // Constructor - RangePattern(::std::unique_ptr<RangePatternBound> lower, - ::std::unique_ptr<RangePatternBound> upper, Location locus, - bool has_ellipsis_syntax = false) : - lower(::std::move(lower)), - upper(::std::move(upper)), has_ellipsis_syntax(has_ellipsis_syntax), locus(locus) {} - - // 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) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - RangePattern& operator=(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; - - return *this; - } - - // default move semantics - RangePattern(RangePattern&& other) = default; - RangePattern& operator=(RangePattern&& other) = default; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RangePattern* clone_pattern_impl() const OVERRIDE { - return new RangePattern(*this); - } - }; - - // AST node for pattern based on dereferencing the pointers given - class ReferencePattern : public Pattern { - bool has_two_amps; - bool is_mut; - // Pattern* pattern; - ::std::unique_ptr<Pattern> pattern; - - Location locus; - - public: - /*~ReferencePattern() { - delete pattern; - }*/ - - ::std::string as_string() const; - - ReferencePattern(::std::unique_ptr<Pattern> pattern, bool is_mut_reference, - bool ref_has_two_amps, Location locus) : - has_two_amps(ref_has_two_amps), - is_mut(is_mut_reference), pattern(::std::move(pattern)), locus(locus) {} - - // Copy constructor requires clone - ReferencePattern(ReferencePattern const& other) : - has_two_amps(other.has_two_amps), is_mut(other.is_mut), - pattern(other.pattern->clone_pattern()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - ReferencePattern& operator=(ReferencePattern const& other) { - pattern = other.pattern->clone_pattern(); - is_mut = other.is_mut; - has_two_amps = other.has_two_amps; - locus = other.locus; - - return *this; - } - - // default move semantics - ReferencePattern(ReferencePattern&& other) = default; - ReferencePattern& operator=(ReferencePattern&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ReferencePattern* clone_pattern_impl() const OVERRIDE { - return new ReferencePattern(*this); - } - }; - - // aka StructPatternEtCetera; potential element in struct pattern - struct StructPatternEtc { - private: - ::std::vector<Attribute> outer_attrs; - - // should this store location data? - - public: - StructPatternEtc(::std::vector<Attribute> outer_attribs) : - outer_attrs(::std::move(outer_attribs)) {} - - // Creates an empty StructPatternEtc - static StructPatternEtc create_empty() { - return StructPatternEtc(::std::vector<Attribute>()); - } - }; - - // Base class for a single field in a struct pattern - abstract - class StructPatternField { - ::std::vector<Attribute> outer_attrs; - /*union { - struct { - //TupleIndex index; - Pattern tuple_pattern; - } tuple_pattern; - struct { - //Identifier ident; - Pattern ident_pattern; - } ident_pattern; - struct { - bool has_ref; - bool has_mut; - //Identifier ident; - } ident; - } pattern;*/ - - Location locus; - - public: - virtual ~StructPatternField() {} - - // Unique pointer custom clone function - ::std::unique_ptr<StructPatternField> clone_struct_pattern_field() const { - return ::std::unique_ptr<StructPatternField>(clone_struct_pattern_field_impl()); - } - - virtual ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - StructPatternField(::std::vector<Attribute> outer_attribs, Location locus) : - outer_attrs(::std::move(outer_attribs)), locus(locus) {} - - // Clone function implementation as pure virtual method - virtual StructPatternField* clone_struct_pattern_field_impl() const = 0; - }; - - // Tuple pattern single field in a struct pattern - class StructPatternFieldTuplePat : public StructPatternField { - TupleIndex index; - // Pattern* tuple_pattern; - ::std::unique_ptr<Pattern> tuple_pattern; - - public: - /*~StructPatternFieldTuplePat() { - delete tuple_pattern; - }*/ - - StructPatternFieldTuplePat(TupleIndex index, ::std::unique_ptr<Pattern> tuple_pattern, - ::std::vector<Attribute> outer_attribs, Location locus) : - StructPatternField(::std::move(outer_attribs), locus), - index(index), tuple_pattern(::std::move(tuple_pattern)) {} - - // Copy constructor requires clone - StructPatternFieldTuplePat(StructPatternFieldTuplePat const& other) : - StructPatternField(other), index(other.index), - tuple_pattern(other.tuple_pattern->clone_pattern()) {} - - // Destructor - define here if required - - // Overload assignment operator to perform clone - StructPatternFieldTuplePat& operator=(StructPatternFieldTuplePat const& other) { - StructPatternField::operator=(other); - tuple_pattern = other.tuple_pattern->clone_pattern(); - index = other.index; - // outer_attrs = other.outer_attrs; - - return *this; - } - - // default move semantics - StructPatternFieldTuplePat(StructPatternFieldTuplePat&& other) = default; - StructPatternFieldTuplePat& operator=(StructPatternFieldTuplePat&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructPatternFieldTuplePat* clone_struct_pattern_field_impl() const OVERRIDE { - return new StructPatternFieldTuplePat(*this); - } - }; - - // Identifier pattern single field in a struct pattern - class StructPatternFieldIdentPat : public StructPatternField { - Identifier ident; - // Pattern* ident_pattern; - ::std::unique_ptr<Pattern> ident_pattern; - - public: - /*~StructPatternFieldIdentPat() { - delete ident_pattern; - }*/ - - StructPatternFieldIdentPat(Identifier ident, ::std::unique_ptr<Pattern> ident_pattern, - ::std::vector<Attribute> outer_attrs, Location locus) : - StructPatternField(::std::move(outer_attrs), locus), - ident(::std::move(ident)), ident_pattern(::std::move(ident_pattern)) {} - - // Copy constructor requires clone - StructPatternFieldIdentPat(StructPatternFieldIdentPat const& other) : - StructPatternField(other), ident(other.ident), - ident_pattern(other.ident_pattern->clone_pattern()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - StructPatternFieldIdentPat& operator=(StructPatternFieldIdentPat const& other) { - StructPatternField::operator=(other); - ident = other.ident; - ident_pattern = other.ident_pattern->clone_pattern(); - // outer_attrs = other.outer_attrs; - - return *this; - } - - // default move semantics - StructPatternFieldIdentPat(StructPatternFieldIdentPat&& other) = default; - StructPatternFieldIdentPat& operator=(StructPatternFieldIdentPat&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructPatternFieldIdentPat* clone_struct_pattern_field_impl() const OVERRIDE { - return new StructPatternFieldIdentPat(*this); - } - }; - - // Identifier only (with no pattern) single field in a struct pattern - class StructPatternFieldIdent : public StructPatternField { - bool has_ref; - bool has_mut; - - Identifier ident; - - public: - StructPatternFieldIdent(Identifier ident, bool is_ref, bool is_mut, - ::std::vector<Attribute> outer_attrs, Location locus) : - StructPatternField(::std::move(outer_attrs), locus), - has_ref(is_ref), has_mut(is_mut), ident(::std::move(ident)) {} - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructPatternFieldIdent* clone_struct_pattern_field_impl() const OVERRIDE { - return new StructPatternFieldIdent(*this); - } - }; - - // Elements of a struct pattern - struct StructPatternElements { - private: - // bool has_struct_pattern_fields; - //::std::vector<StructPatternField> fields; - ::std::vector< ::std::unique_ptr<StructPatternField> > fields; - - bool has_struct_pattern_etc; - StructPatternEtc etc; - - // must have at least one of the two and maybe both - - // should this store location data? - - public: - // Returns whether there are any struct pattern fields - inline bool has_struct_pattern_fields() const { - return !fields.empty(); - } - - // Returns whether the struct pattern elements is entirely empty (no fields, no etc). - inline bool is_empty() const { - return !has_struct_pattern_fields() && !has_struct_pattern_etc; - } - - // Constructor for StructPatternElements with both (potentially) - StructPatternElements( - ::std::vector< ::std::unique_ptr<StructPatternField> > fields, StructPatternEtc etc) : - fields(::std::move(fields)), - has_struct_pattern_etc(true), etc(::std::move(etc)) {} - - // Constructor for StructPatternElements with no StructPatternEtc - StructPatternElements(::std::vector< ::std::unique_ptr<StructPatternField> > fields) : - fields(::std::move(fields)), has_struct_pattern_etc(false), - etc(StructPatternEtc::create_empty()) {} - - // Copy constructor with vector clone - StructPatternElements(StructPatternElements const& other) : - has_struct_pattern_etc(other.has_struct_pattern_etc), etc(other.etc) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_struct_pattern_field()); - } - } - - // Overloaded assignment operator with vector clone - StructPatternElements& operator=(StructPatternElements const& other) { - etc = other.etc; - has_struct_pattern_etc = other.has_struct_pattern_etc; - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - fields.reserve(other.fields.size()); - - for (const auto& e : other.fields) { - fields.push_back(e->clone_struct_pattern_field()); - } - - return *this; - } - - // move constructors - StructPatternElements(StructPatternElements&& other) = default; - StructPatternElements& operator=(StructPatternElements&& other) = default; - - // Creates an empty StructPatternElements - static StructPatternElements create_empty() { - return StructPatternElements( - ::std::vector< ::std::unique_ptr<StructPatternField> >()); - } - - ::std::string as_string() const; - }; +// Class representing TuplePattern patterns where there is only a single pattern +/*class TuplePatternItemsSingle : public TuplePatternItems { + // Pattern pattern; + ::std::unique_ptr<Pattern> pattern; - // Struct pattern AST node representation - class StructPattern : public Pattern { - PathInExpression path; - - // bool has_struct_pattern_elements; - StructPatternElements elems; - - // TODO: should this store location data? Accessor uses path location data. - - public: - ::std::string as_string() const; - - // Constructs a struct pattern from specified StructPatternElements - StructPattern(PathInExpression struct_path, - StructPatternElements elems = StructPatternElements::create_empty()) : - path(::std::move(struct_path)), - elems(::std::move(elems)) {} - - // TODO: constructor to construct via elements included in StructPatternElements - - // Returns whether struct pattern has any struct pattern elements (if not, it is empty). - inline bool has_struct_pattern_elems() const { - return !elems.is_empty(); - } - - Location get_locus() const { - return path.get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual StructPattern* clone_pattern_impl() const OVERRIDE { - return new StructPattern(*this); - } - }; - - // Base abstract class for patterns used in TupleStructPattern - class TupleStructItems { - public: - virtual ~TupleStructItems() {} - - // TODO: should this store location data? - - // Unique pointer custom clone function - ::std::unique_ptr<TupleStructItems> clone_tuple_struct_items() const { - return ::std::unique_ptr<TupleStructItems>(clone_tuple_struct_items_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual TupleStructItems* clone_tuple_struct_items_impl() const = 0; - }; - - // Class for non-ranged tuple struct pattern patterns - class TupleStructItemsNoRange : public TupleStructItems { - //::std::vector<Pattern> patterns; - ::std::vector< ::std::unique_ptr<Pattern> > patterns; + public: + TuplePatternItemsSingle(Pattern* pattern) : pattern(pattern) {} - public: - TupleStructItemsNoRange(::std::vector< ::std::unique_ptr<Pattern> > patterns) : - patterns(::std::move(patterns)) {} - - // Copy constructor with vector clone - TupleStructItemsNoRange(TupleStructItemsNoRange const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - patterns.reserve(other.patterns.size()); - - for (const auto& e : other.patterns) { - patterns.push_back(e->clone_pattern()); - } - } + // Copy constructor uses clone + TuplePatternItemsSingle(TuplePatternItemsSingle const& other) : + pattern(other.pattern->clone_pattern()) {} - // Overloaded assignment operator with vector clone - TupleStructItemsNoRange& operator=(TupleStructItemsNoRange const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - patterns.reserve(other.patterns.size()); + // Destructor - define here if required - for (const auto& e : other.patterns) { - patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - TupleStructItemsNoRange(TupleStructItemsNoRange&& other) = default; - TupleStructItemsNoRange& operator=(TupleStructItemsNoRange&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleStructItemsNoRange* clone_tuple_struct_items_impl() const OVERRIDE { - return new TupleStructItemsNoRange(*this); - } - }; - - // Class for ranged tuple struct pattern patterns - class TupleStructItemsRange : public TupleStructItems { - /*::std::vector<Pattern> lower_patterns; - ::std::vector<Pattern> upper_patterns;*/ - ::std::vector< ::std::unique_ptr<Pattern> > lower_patterns; - ::std::vector< ::std::unique_ptr<Pattern> > upper_patterns; - - public: - TupleStructItemsRange(::std::vector< ::std::unique_ptr<Pattern> > lower_patterns, - ::std::vector< ::std::unique_ptr<Pattern> > upper_patterns) : - lower_patterns(::std::move(lower_patterns)), - upper_patterns(::std::move(upper_patterns)) {} - - // Copy constructor with vector clone - TupleStructItemsRange(TupleStructItemsRange const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - lower_patterns.reserve(other.lower_patterns.size()); - - for (const auto& e : other.lower_patterns) { - lower_patterns.push_back(e->clone_pattern()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - upper_patterns.reserve(other.upper_patterns.size()); - - for (const auto& e : other.upper_patterns) { - upper_patterns.push_back(e->clone_pattern()); - } - } - - // Overloaded assignment operator to clone - TupleStructItemsRange& operator=(TupleStructItemsRange const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - lower_patterns.reserve(other.lower_patterns.size()); - - for (const auto& e : other.lower_patterns) { - lower_patterns.push_back(e->clone_pattern()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - upper_patterns.reserve(other.upper_patterns.size()); - - for (const auto& e : other.upper_patterns) { - upper_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - TupleStructItemsRange(TupleStructItemsRange&& other) = default; - TupleStructItemsRange& operator=(TupleStructItemsRange&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleStructItemsRange* clone_tuple_struct_items_impl() const OVERRIDE { - return new TupleStructItemsRange(*this); - } - }; - - // AST node representing a tuple struct pattern - class TupleStructPattern : public Pattern { - PathInExpression path; - // TupleStructItems items; - ::std::unique_ptr<TupleStructItems> items; - - // TOOD: should this store location data? current accessor uses path location data - - public: - ::std::string as_string() const; - - TupleStructPattern( - PathInExpression tuple_struct_path, ::std::unique_ptr<TupleStructItems> items) : - path(::std::move(tuple_struct_path)), - items(::std::move(items)) {} - - // Copy constructor required to clone - TupleStructPattern(TupleStructPattern const& other) : - path(other.path), items(other.items->clone_tuple_struct_items()) {} - - // Destructor - define here if required - - // Operator overload assignment operator to clone - TupleStructPattern& operator=(TupleStructPattern const& other) { - path = other.path; - items = other.items->clone_tuple_struct_items(); - - return *this; - } - - // move constructors - TupleStructPattern(TupleStructPattern&& other) = default; - TupleStructPattern& operator=(TupleStructPattern&& other) = default; - - Location get_locus() const { - return path.get_locus(); - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleStructPattern* clone_pattern_impl() const OVERRIDE { - return new TupleStructPattern(*this); - } - }; - - // Base abstract class representing TuplePattern patterns - class TuplePatternItems { - public: - virtual ~TuplePatternItems() {} - - // TODO: should this store location data? - - // Unique pointer custom clone function - ::std::unique_ptr<TuplePatternItems> clone_tuple_pattern_items() const { - return ::std::unique_ptr<TuplePatternItems>(clone_tuple_pattern_items_impl()); - } - - virtual ::std::string as_string() const = 0; - - virtual void accept_vis(ASTVisitor& vis) = 0; - - protected: - // pure virtual clone implementation - virtual TuplePatternItems* clone_tuple_pattern_items_impl() const = 0; - }; - - // Class representing TuplePattern patterns where there is only a single pattern - /*class TuplePatternItemsSingle : public TuplePatternItems { - // Pattern pattern; - ::std::unique_ptr<Pattern> pattern; - - public: - TuplePatternItemsSingle(Pattern* pattern) : pattern(pattern) {} - - // Copy constructor uses clone - TuplePatternItemsSingle(TuplePatternItemsSingle const& other) : - pattern(other.pattern->clone_pattern()) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - TuplePatternItemsSingle& operator=(TuplePatternItemsSingle const& other) { - pattern = other.pattern->clone_pattern(); - - return *this; - } - - // move constructors - TuplePatternItemsSingle(TuplePatternItemsSingle&& other) = default; - TuplePatternItemsSingle& operator=(TuplePatternItemsSingle&& other) = default; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TuplePatternItemsSingle* clone_tuple_pattern_items_impl() const OVERRIDE { - return new TuplePatternItemsSingle(*this); - } - };*/ - // removed in favour of single-element TuplePatternItemsMultiple - - // Class representing TuplePattern patterns where there are multiple patterns - class TuplePatternItemsMultiple : public TuplePatternItems { - //::std::vector<Pattern> patterns; - ::std::vector< ::std::unique_ptr<Pattern> > patterns; - - public: - TuplePatternItemsMultiple(::std::vector< ::std::unique_ptr<Pattern> > patterns) : - patterns(::std::move(patterns)) {} - - // Copy constructor with vector clone - TuplePatternItemsMultiple(TuplePatternItemsMultiple const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - patterns.reserve(other.patterns.size()); - - for (const auto& e : other.patterns) { - patterns.push_back(e->clone_pattern()); - } - } - - // Overloaded assignment operator to vector clone - TuplePatternItemsMultiple& operator=(TuplePatternItemsMultiple const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - patterns.reserve(other.patterns.size()); - - for (const auto& e : other.patterns) { - patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - TuplePatternItemsMultiple(TuplePatternItemsMultiple&& other) = default; - TuplePatternItemsMultiple& operator=(TuplePatternItemsMultiple&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TuplePatternItemsMultiple* clone_tuple_pattern_items_impl() const OVERRIDE { - return new TuplePatternItemsMultiple(*this); - } - }; - - // Class representing TuplePattern patterns where there are a range of patterns - class TuplePatternItemsRanged : public TuplePatternItems { - /*::std::vector<Pattern> lower_patterns; - ::std::vector<Pattern> upper_patterns;*/ - ::std::vector< ::std::unique_ptr<Pattern> > lower_patterns; - ::std::vector< ::std::unique_ptr<Pattern> > upper_patterns; - - public: - TuplePatternItemsRanged(::std::vector< ::std::unique_ptr<Pattern> > lower_patterns, - ::std::vector< ::std::unique_ptr<Pattern> > upper_patterns) : - lower_patterns(::std::move(lower_patterns)), - upper_patterns(::std::move(upper_patterns)) {} - - // Copy constructor with vector clone - TuplePatternItemsRanged(TuplePatternItemsRanged const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - lower_patterns.reserve(other.lower_patterns.size()); - - for (const auto& e : other.lower_patterns) { - lower_patterns.push_back(e->clone_pattern()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - upper_patterns.reserve(other.upper_patterns.size()); - - for (const auto& e : other.upper_patterns) { - upper_patterns.push_back(e->clone_pattern()); - } - } - - // Overloaded assignment operator to clone - TuplePatternItemsRanged& operator=(TuplePatternItemsRanged const& other) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - lower_patterns.reserve(other.lower_patterns.size()); - - for (const auto& e : other.lower_patterns) { - lower_patterns.push_back(e->clone_pattern()); - } - - // crappy vector unique pointer clone - TODO is there a better way of doing this? - upper_patterns.reserve(other.upper_patterns.size()); - - for (const auto& e : other.upper_patterns) { - upper_patterns.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - TuplePatternItemsRanged(TuplePatternItemsRanged&& other) = default; - TuplePatternItemsRanged& operator=(TuplePatternItemsRanged&& other) = default; - - ::std::string as_string() const; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TuplePatternItemsRanged* clone_tuple_pattern_items_impl() const OVERRIDE { - return new TuplePatternItemsRanged(*this); - } - }; - - // AST node representing a tuple pattern - class TuplePattern : public Pattern { - // bool has_tuple_pattern_items; - // TuplePatternItems items; - ::std::unique_ptr<TuplePatternItems> items; - - Location locus; - - public: - ::std::string as_string() const; - - // Returns true if the tuple pattern has items - inline bool has_tuple_pattern_items() const { - return items != NULL; - } - - TuplePattern(::std::unique_ptr<TuplePatternItems> items, Location locus) : - items(::std::move(items)), locus(locus) {} - - // Copy constructor requires clone - TuplePattern(TuplePattern const& other) : - items(other.items->clone_tuple_pattern_items()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - TuplePattern& operator=(TuplePattern const& other) { - items = other.items->clone_tuple_pattern_items(); - locus = other.locus; - - return *this; - } - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TuplePattern* clone_pattern_impl() const OVERRIDE { - return new TuplePattern(*this); - } - }; - - // AST node representing a pattern in parentheses, used to control precedence - class GroupedPattern : public Pattern { - // Pattern pattern_in_parens; - ::std::unique_ptr<Pattern> pattern_in_parens; - - Location locus; - - public: - ::std::string as_string() const { - return "(" + pattern_in_parens->as_string() + ")"; - } - - GroupedPattern(::std::unique_ptr<Pattern> pattern_in_parens, Location locus) : - pattern_in_parens(::std::move(pattern_in_parens)), locus(locus) {} - - // Copy constructor uses clone - GroupedPattern(GroupedPattern const& other) : - pattern_in_parens(other.pattern_in_parens->clone_pattern()), locus(other.locus) {} - - // Destructor - define here if required - - // Overload assignment operator to clone - GroupedPattern& operator=(GroupedPattern const& other) { - pattern_in_parens = other.pattern_in_parens->clone_pattern(); - locus = other.locus; - - return *this; - } - - // default move semantics - GroupedPattern(GroupedPattern&& other) = default; - GroupedPattern& operator=(GroupedPattern&& other) = default; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual GroupedPattern* clone_pattern_impl() const OVERRIDE { - return new GroupedPattern(*this); - } - }; - - // AST node representing patterns that can match slices and arrays - class SlicePattern : public Pattern { - //::std::vector<Pattern> items; - ::std::vector< ::std::unique_ptr<Pattern> > items; - - Location locus; - - public: - ::std::string as_string() const; - - SlicePattern(::std::vector< ::std::unique_ptr<Pattern> > items, Location locus) : - items(::std::move(items)), locus(locus) {} - - // Copy constructor with vector clone - SlicePattern(SlicePattern const& other) : locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_pattern()); - } - } - - // Overloaded assignment operator to vector clone - SlicePattern& operator=(SlicePattern const& other) { - locus = other.locus; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - items.reserve(other.items.size()); - - for (const auto& e : other.items) { - items.push_back(e->clone_pattern()); - } - - return *this; - } - - // move constructors - SlicePattern(SlicePattern&& other) = default; - SlicePattern& operator=(SlicePattern&& other) = default; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual SlicePattern* clone_pattern_impl() const OVERRIDE { - return new SlicePattern(*this); - } - }; - - // forward decl PathExprSegment - // class PathExprSegment; - - // Moved definition to rust-path.h - class PathPattern; + // Overload assignment operator to clone + TuplePatternItemsSingle& operator=(TuplePatternItemsSingle const& other) { + pattern = other.pattern->clone_pattern(); + + return *this; + } - // Forward decls for paths (defined in rust-path.h) - class PathInExpression; - class QualifiedPathInExpression; + // move constructors + TuplePatternItemsSingle(TuplePatternItemsSingle&& other) = default; + TuplePatternItemsSingle& operator=(TuplePatternItemsSingle&& other) = +default; - // Replaced with forward decl - defined in rust-macro.h - class MacroInvocation; - /*class MacroInvocation : public Pattern { - public: - ::std::string as_string() const; - };*/ + protected: + // Use covariance to implement clone function as returning this object +rather than base virtual TuplePatternItemsSingle* +clone_tuple_pattern_items_impl() const OVERRIDE { return new +TuplePatternItemsSingle(*this); } -} +};*/ +// removed in favour of single-element TuplePatternItemsMultiple + +// Class representing TuplePattern patterns where there are multiple patterns +class TuplePatternItemsMultiple : public TuplePatternItems +{ + //::std::vector<Pattern> patterns; + ::std::vector< ::std::unique_ptr<Pattern> > patterns; + +public: + TuplePatternItemsMultiple ( + ::std::vector< ::std::unique_ptr<Pattern> > patterns) + : patterns (::std::move (patterns)) + {} + + // Copy constructor with vector clone + TuplePatternItemsMultiple (TuplePatternItemsMultiple const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + patterns.reserve (other.patterns.size ()); + + for (const auto &e : other.patterns) + { + patterns.push_back (e->clone_pattern ()); + } + } + + // Overloaded assignment operator to vector clone + TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + patterns.reserve (other.patterns.size ()); + + for (const auto &e : other.patterns) + { + patterns.push_back (e->clone_pattern ()); + } + + return *this; + } + + // move constructors + TuplePatternItemsMultiple (TuplePatternItemsMultiple &&other) = default; + TuplePatternItemsMultiple &operator= (TuplePatternItemsMultiple &&other) + = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TuplePatternItemsMultiple * + clone_tuple_pattern_items_impl () const OVERRIDE + { + return new TuplePatternItemsMultiple (*this); + } +}; + +// Class representing TuplePattern patterns where there are a range of patterns +class TuplePatternItemsRanged : public TuplePatternItems +{ + /*::std::vector<Pattern> lower_patterns; + ::std::vector<Pattern> upper_patterns;*/ + ::std::vector< ::std::unique_ptr<Pattern> > lower_patterns; + ::std::vector< ::std::unique_ptr<Pattern> > upper_patterns; + +public: + TuplePatternItemsRanged ( + ::std::vector< ::std::unique_ptr<Pattern> > lower_patterns, + ::std::vector< ::std::unique_ptr<Pattern> > upper_patterns) + : lower_patterns (::std::move (lower_patterns)), + upper_patterns (::std::move (upper_patterns)) + {} + + // Copy constructor with vector clone + TuplePatternItemsRanged (TuplePatternItemsRanged const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + lower_patterns.reserve (other.lower_patterns.size ()); + + for (const auto &e : other.lower_patterns) + { + lower_patterns.push_back (e->clone_pattern ()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + upper_patterns.reserve (other.upper_patterns.size ()); + + for (const auto &e : other.upper_patterns) + { + upper_patterns.push_back (e->clone_pattern ()); + } + } + + // Overloaded assignment operator to clone + TuplePatternItemsRanged &operator= (TuplePatternItemsRanged const &other) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + lower_patterns.reserve (other.lower_patterns.size ()); + + for (const auto &e : other.lower_patterns) + { + lower_patterns.push_back (e->clone_pattern ()); + } + + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + upper_patterns.reserve (other.upper_patterns.size ()); + + for (const auto &e : other.upper_patterns) + { + upper_patterns.push_back (e->clone_pattern ()); + } + + return *this; + } + + // move constructors + TuplePatternItemsRanged (TuplePatternItemsRanged &&other) = default; + TuplePatternItemsRanged &operator= (TuplePatternItemsRanged &&other) + = default; + + ::std::string as_string () const; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TuplePatternItemsRanged * + clone_tuple_pattern_items_impl () const OVERRIDE + { + return new TuplePatternItemsRanged (*this); + } +}; + +// AST node representing a tuple pattern +class TuplePattern : public Pattern +{ + // bool has_tuple_pattern_items; + // TuplePatternItems items; + ::std::unique_ptr<TuplePatternItems> items; + + Location locus; + +public: + ::std::string as_string () const; + + // Returns true if the tuple pattern has items + inline bool has_tuple_pattern_items () const { return items != NULL; } + + TuplePattern (::std::unique_ptr<TuplePatternItems> items, Location locus) + : items (::std::move (items)), locus (locus) + {} + + // Copy constructor requires clone + TuplePattern (TuplePattern const &other) + : items (other.items->clone_tuple_pattern_items ()), locus (other.locus) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone + TuplePattern &operator= (TuplePattern const &other) + { + items = other.items->clone_tuple_pattern_items (); + locus = other.locus; + + return *this; + } + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TuplePattern *clone_pattern_impl () const OVERRIDE + { + return new TuplePattern (*this); + } +}; + +// AST node representing a pattern in parentheses, used to control precedence +class GroupedPattern : public Pattern +{ + // Pattern pattern_in_parens; + ::std::unique_ptr<Pattern> pattern_in_parens; + + Location locus; + +public: + ::std::string as_string () const + { + return "(" + pattern_in_parens->as_string () + ")"; + } + + GroupedPattern (::std::unique_ptr<Pattern> pattern_in_parens, Location locus) + : pattern_in_parens (::std::move (pattern_in_parens)), locus (locus) + {} + + // Copy constructor uses clone + GroupedPattern (GroupedPattern const &other) + : pattern_in_parens (other.pattern_in_parens->clone_pattern ()), + locus (other.locus) + {} + + // Destructor - define here if required + + // Overload assignment operator to clone + GroupedPattern &operator= (GroupedPattern const &other) + { + pattern_in_parens = other.pattern_in_parens->clone_pattern (); + locus = other.locus; + + return *this; + } + + // default move semantics + GroupedPattern (GroupedPattern &&other) = default; + GroupedPattern &operator= (GroupedPattern &&other) = default; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual GroupedPattern *clone_pattern_impl () const OVERRIDE + { + return new GroupedPattern (*this); + } +}; + +// AST node representing patterns that can match slices and arrays +class SlicePattern : public Pattern +{ + //::std::vector<Pattern> items; + ::std::vector< ::std::unique_ptr<Pattern> > items; + + Location locus; + +public: + ::std::string as_string () const; + + SlicePattern (::std::vector< ::std::unique_ptr<Pattern> > items, + Location locus) + : items (::std::move (items)), locus (locus) + {} + + // Copy constructor with vector clone + SlicePattern (SlicePattern const &other) : locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + items.reserve (other.items.size ()); + + for (const auto &e : other.items) + { + items.push_back (e->clone_pattern ()); + } + } + + // Overloaded assignment operator to vector clone + SlicePattern &operator= (SlicePattern const &other) + { + locus = other.locus; + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + items.reserve (other.items.size ()); + + for (const auto &e : other.items) + { + items.push_back (e->clone_pattern ()); + } + + return *this; + } + + // move constructors + SlicePattern (SlicePattern &&other) = default; + SlicePattern &operator= (SlicePattern &&other) = default; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual SlicePattern *clone_pattern_impl () const OVERRIDE + { + return new SlicePattern (*this); + } +}; + +// forward decl PathExprSegment +// class PathExprSegment; + +// Moved definition to rust-path.h +class PathPattern; + +// Forward decls for paths (defined in rust-path.h) +class PathInExpression; +class QualifiedPathInExpression; + +// Replaced with forward decl - defined in rust-macro.h +class MacroInvocation; +/*class MacroInvocation : public Pattern { + public: + ::std::string as_string() const; +};*/ +} // namespace AST +} // namespace Rust #endif diff --git a/gcc/rust/ast/rust-stmt.h b/gcc/rust/ast/rust-stmt.h index 767b620..08d5ff8 100644 --- a/gcc/rust/ast/rust-stmt.h +++ b/gcc/rust/ast/rust-stmt.h @@ -6,240 +6,254 @@ #include "rust-expr.h" namespace Rust { - namespace AST { - // Just a semi-colon, which apparently is a statement. - class EmptyStmt : public Stmt { - Location locus; - - public: - ::std::string as_string() const { - return ::std::string(1, ';'); - } - - EmptyStmt(Location locus) : locus(locus) {} - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual EmptyStmt* clone_stmt_impl() const OVERRIDE { - return new EmptyStmt(*this); - } - }; - - /* This is syntactically identical to declaring an item inside a module BUT it has block - * scope. Type of "declaration statement" as it introduces new name into scope */ - /*class ItemStatement : public Statement { - // TODO: put in same params as regular item - // maybe even merge data structure with module item? - - public: - ::std::string as_string() const; - };*/ - // removed - just made item inherit from statement - - /* Variable assignment let statement - type of "declaration statement" as it introduces new - * name into scope */ - class LetStmt : public Stmt { - // bool has_outer_attrs; - ::std::vector<Attribute> outer_attrs; - - // Pattern variables_pattern; - ::std::unique_ptr<Pattern> variables_pattern; - - // bool has_type; - // Type type; - ::std::unique_ptr<Type> type; - - // bool has_init_expr; - // Expr* init_expr; - ::std::unique_ptr<Expr> init_expr; - - Location locus; - - public: - // Returns whether let statement has outer attributes. - inline bool has_outer_attrs() const { - return !outer_attrs.empty(); - } - - // Returns whether let statement has a given return type. - inline bool has_type() const { - return type != NULL; - } - - // Returns whether let statement has an initialisation expression. - inline bool has_init_expr() const { - return init_expr != NULL; - } - - /*~LetStatement() { - if (has_init_expr) { - delete init_expr; - } - }*/ - - ::std::string as_string() const; - - LetStmt(::std::unique_ptr<Pattern> variables_pattern, ::std::unique_ptr<Expr> init_expr, - ::std::unique_ptr<Type> type, ::std::vector<Attribute> outer_attrs, Location 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) {} - - // Copy constructor with clone - LetStmt(LetStmt const& other) : - outer_attrs(other.outer_attrs), - variables_pattern(other.variables_pattern->clone_pattern()), - type(other.type->clone_type()), init_expr(other.init_expr->clone_expr()), - locus(other.locus) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - LetStmt& operator=(LetStmt const& other) { - variables_pattern = other.variables_pattern->clone_pattern(); - init_expr = other.init_expr->clone_expr(); - type = other.type->clone_type(); - outer_attrs = other.outer_attrs; - locus = other.locus; - - return *this; - } - - // move constructors - LetStmt(LetStmt&& other) = default; - LetStmt& operator=(LetStmt&& other) = default; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual LetStmt* clone_stmt_impl() const OVERRIDE { - return new LetStmt(*this); - } - }; - - // Abstract base class for expression statements (statements containing an expression) - class ExprStmt : public Stmt { - // TODO: add any useful virtual functions - - Location locus; - - public: - Location get_locus() const { - return locus; - } - - protected: - ExprStmt(Location locus) : locus(locus) {} - }; - - /* Statement containing an expression without a block (or, due to technical difficulties, can - * only be guaranteed to hold an expression). */ - class ExprStmtWithoutBlock : public ExprStmt { - // ExprWithoutBlock* expr; - /* HACK: cannot ensure type safety of ExprWithoutBlock due to Pratt parsing, so have to - * store more general type of Expr. FIXME: fix this issue somehow or redesign AST. */ - //::std::unique_ptr<ExprWithoutBlock> expr; - ::std::unique_ptr<Expr> expr; - - public: - /*~ExpressionStatementWithoutBlock() { - delete expr; - }*/ - - ::std::string as_string() const; - - // ExprStmtWithoutBlock(::std::unique_ptr<ExprWithoutBlock> expr) : - // expr(::std::move(expr)) {} - ExprStmtWithoutBlock(::std::unique_ptr<Expr> expr, Location locus) : - ExprStmt(locus), expr(::std::move(expr)) {} - - // Copy constructor with clone - ExprStmtWithoutBlock(ExprStmtWithoutBlock const& other) : - ExprStmt(other), expr(other.expr->clone_expr /*_without_block*/ ()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - ExprStmtWithoutBlock& operator=(ExprStmtWithoutBlock const& other) { - ExprStmt::operator=(other); - expr = other.expr->clone_expr /*_without_block*/ (); - - return *this; - } - - // move constructors - ExprStmtWithoutBlock(ExprStmtWithoutBlock&& other) = default; - ExprStmtWithoutBlock& operator=(ExprStmtWithoutBlock&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ExprStmtWithoutBlock* clone_stmt_impl() const OVERRIDE { - return new ExprStmtWithoutBlock(*this); - } - }; - - // Statement containing an expression with a block - class ExprStmtWithBlock : public ExprStmt { - // ExprWithBlock* expr; - ::std::unique_ptr<ExprWithBlock> expr; - - public: - /*~ExpressionStatementWithBlock() { - delete expr; - }*/ - - ::std::string as_string() const; - - ExprStmtWithBlock(::std::unique_ptr<ExprWithBlock> expr, Location locus) : - ExprStmt(locus), expr(::std::move(expr)) {} - - // Copy constructor with clone - ExprStmtWithBlock(ExprStmtWithBlock const& other) : - ExprStmt(other), expr(other.expr->clone_expr_with_block()) {} - - // Destructor - define here if required - - // Overloaded assignment operator to clone - ExprStmtWithBlock& operator=(ExprStmtWithBlock const& other) { - ExprStmt::operator=(other); - expr = other.expr->clone_expr_with_block(); - - return *this; - } - - // move constructors - ExprStmtWithBlock(ExprStmtWithBlock&& other) = default; - ExprStmtWithBlock& operator=(ExprStmtWithBlock&& other) = default; - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ExprStmtWithBlock* clone_stmt_impl() const OVERRIDE { - return new ExprStmtWithBlock(*this); - } - }; - - // Replaced definition of MacroInvocationSemi with forward decl - defined in rust-macro.h - class MacroInvocationSemi; - /*class MacroInvocationSemi : public Statement { - public: - ::std::string as_string() const; - };*/ - } -} +namespace AST { +// Just a semi-colon, which apparently is a statement. +class EmptyStmt : public Stmt +{ + Location locus; + +public: + ::std::string as_string () const { return ::std::string (1, ';'); } + + EmptyStmt (Location locus) : locus (locus) {} + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual EmptyStmt *clone_stmt_impl () const OVERRIDE + { + return new EmptyStmt (*this); + } +}; + +/* This is syntactically identical to declaring an item inside a module BUT it + * has block scope. Type of "declaration statement" as it introduces new name + * into scope */ +/*class ItemStatement : public Statement { + // TODO: put in same params as regular item + // maybe even merge data structure with module item? + + public: + ::std::string as_string() const; +};*/ +// removed - just made item inherit from statement + +/* Variable assignment let statement - type of "declaration statement" as it + * introduces new name into scope */ +class LetStmt : public Stmt +{ + // bool has_outer_attrs; + ::std::vector<Attribute> outer_attrs; + + // Pattern variables_pattern; + ::std::unique_ptr<Pattern> variables_pattern; + + // bool has_type; + // Type type; + ::std::unique_ptr<Type> type; + + // bool has_init_expr; + // Expr* init_expr; + ::std::unique_ptr<Expr> init_expr; + + Location locus; + +public: + // Returns whether let statement has outer attributes. + inline bool has_outer_attrs () const { return !outer_attrs.empty (); } + + // Returns whether let statement has a given return type. + inline bool has_type () const { return type != NULL; } + + // Returns whether let statement has an initialisation expression. + inline bool has_init_expr () const { return init_expr != NULL; } + + /*~LetStatement() { + if (has_init_expr) { + delete init_expr; + } + }*/ + + ::std::string as_string () const; + + LetStmt (::std::unique_ptr<Pattern> variables_pattern, + ::std::unique_ptr<Expr> init_expr, ::std::unique_ptr<Type> type, + ::std::vector<Attribute> outer_attrs, Location 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) + {} + + // Copy constructor with clone + LetStmt (LetStmt const &other) + : outer_attrs (other.outer_attrs), + variables_pattern (other.variables_pattern->clone_pattern ()), + type (other.type->clone_type ()), + init_expr (other.init_expr->clone_expr ()), locus (other.locus) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + LetStmt &operator= (LetStmt const &other) + { + variables_pattern = other.variables_pattern->clone_pattern (); + init_expr = other.init_expr->clone_expr (); + type = other.type->clone_type (); + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + LetStmt (LetStmt &&other) = default; + LetStmt &operator= (LetStmt &&other) = default; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual LetStmt *clone_stmt_impl () const OVERRIDE + { + return new LetStmt (*this); + } +}; + +// Abstract base class for expression statements (statements containing an +// expression) +class ExprStmt : public Stmt +{ + // TODO: add any useful virtual functions + + Location locus; + +public: + Location get_locus () const { return locus; } + +protected: + ExprStmt (Location locus) : locus (locus) {} +}; + +/* Statement containing an expression without a block (or, due to technical + * difficulties, can only be guaranteed to hold an expression). */ +class ExprStmtWithoutBlock : public ExprStmt +{ + // ExprWithoutBlock* expr; + /* HACK: cannot ensure type safety of ExprWithoutBlock due to Pratt parsing, + * so have to store more general type of Expr. FIXME: fix this issue somehow + * or redesign AST. */ + //::std::unique_ptr<ExprWithoutBlock> expr; + ::std::unique_ptr<Expr> expr; + +public: + /*~ExpressionStatementWithoutBlock() { + delete expr; + }*/ + + ::std::string as_string () const; + + // ExprStmtWithoutBlock(::std::unique_ptr<ExprWithoutBlock> expr) : + // expr(::std::move(expr)) {} + ExprStmtWithoutBlock (::std::unique_ptr<Expr> expr, Location locus) + : ExprStmt (locus), expr (::std::move (expr)) + {} + + // Copy constructor with clone + ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) + : ExprStmt (other), expr (other.expr->clone_expr /*_without_block*/ ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other) + { + ExprStmt::operator= (other); + expr = other.expr->clone_expr /*_without_block*/ (); + + return *this; + } + + // move constructors + ExprStmtWithoutBlock (ExprStmtWithoutBlock &&other) = default; + ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ExprStmtWithoutBlock *clone_stmt_impl () const OVERRIDE + { + return new ExprStmtWithoutBlock (*this); + } +}; + +// Statement containing an expression with a block +class ExprStmtWithBlock : public ExprStmt +{ + // ExprWithBlock* expr; + ::std::unique_ptr<ExprWithBlock> expr; + +public: + /*~ExpressionStatementWithBlock() { + delete expr; + }*/ + + ::std::string as_string () const; + + ExprStmtWithBlock (::std::unique_ptr<ExprWithBlock> expr, Location locus) + : ExprStmt (locus), expr (::std::move (expr)) + {} + + // Copy constructor with clone + ExprStmtWithBlock (ExprStmtWithBlock const &other) + : ExprStmt (other), expr (other.expr->clone_expr_with_block ()) + {} + + // Destructor - define here if required + + // Overloaded assignment operator to clone + ExprStmtWithBlock &operator= (ExprStmtWithBlock const &other) + { + ExprStmt::operator= (other); + expr = other.expr->clone_expr_with_block (); + + return *this; + } + + // move constructors + ExprStmtWithBlock (ExprStmtWithBlock &&other) = default; + ExprStmtWithBlock &operator= (ExprStmtWithBlock &&other) = default; + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ExprStmtWithBlock *clone_stmt_impl () const OVERRIDE + { + return new ExprStmtWithBlock (*this); + } +}; + +// Replaced definition of MacroInvocationSemi with forward decl - defined in +// rust-macro.h +class MacroInvocationSemi; +/*class MacroInvocationSemi : public Statement { + public: + ::std::string as_string() const; +};*/ +} // namespace AST +} // namespace Rust #endif diff --git a/gcc/rust/ast/rust-type.h b/gcc/rust/ast/rust-type.h index 2ca973a..cacdd55 100644 --- a/gcc/rust/ast/rust-type.h +++ b/gcc/rust/ast/rust-type.h @@ -5,824 +5,916 @@ #include "rust-path.h" namespace Rust { - namespace AST { - // definitions moved to rust-ast.h - class TypeParamBound; - class Lifetime; - - // A trait bound - class TraitBound : public TypeParamBound { - bool in_parens; - bool opening_question_mark; - - // bool has_for_lifetimes; - // LifetimeParams for_lifetimes; - ::std::vector<LifetimeParam> for_lifetimes; // inlined LifetimeParams - - TypePath type_path; - - Location locus; - - public: - // Returns whether trait bound has "for" lifetimes - inline bool has_for_lifetimes() const { - return !for_lifetimes.empty(); - } - - TraitBound(TypePath type_path, Location locus, bool in_parens = false, - bool opening_question_mark = false, - ::std::vector<LifetimeParam> for_lifetimes = ::std::vector<LifetimeParam>()) : - in_parens(in_parens), - opening_question_mark(opening_question_mark), for_lifetimes(::std::move(for_lifetimes)), - type_path(::std::move(type_path)), locus(locus) {} - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Clone function implementation as (not pure) virtual method - virtual TraitBound* clone_type_param_bound_impl() const { - return new TraitBound(*this); - } - }; - - // definition moved to rust-ast.h - class TypeNoBounds; - - // An impl trait? Poor reference material here. - class ImplTraitType : public Type { - // TypeParamBounds type_param_bounds; - ::std::vector< ::std::unique_ptr<TypeParamBound> > type_param_bounds; // inlined form - - Location locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ImplTraitType* clone_type_impl() const OVERRIDE { - return new ImplTraitType(*this); - } - - public: - ImplTraitType( - ::std::vector< ::std::unique_ptr<TypeParamBound> > type_param_bounds, Location locus) : - type_param_bounds(::std::move(type_param_bounds)), - locus(locus) {} - - // copy constructor with vector clone - ImplTraitType(ImplTraitType const& other) : locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - } - - // overloaded assignment operator to clone - ImplTraitType& operator=(ImplTraitType const& other) { - locus = other.locus; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - - return *this; - } - - // move constructors - ImplTraitType(ImplTraitType&& other) = default; - ImplTraitType& operator=(ImplTraitType&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - // An opaque value of another type that implements a set of traits - class TraitObjectType : public Type { - bool has_dyn; - // TypeParamBounds type_param_bounds; - ::std::vector< ::std::unique_ptr<TypeParamBound> > type_param_bounds; // inlined form - - Location locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TraitObjectType* clone_type_impl() const OVERRIDE { - return new TraitObjectType(*this); - } - - public: - TraitObjectType(::std::vector< ::std::unique_ptr<TypeParamBound> > type_param_bounds, - Location locus, bool is_dyn_dispatch = false) : - has_dyn(is_dyn_dispatch), - type_param_bounds(::std::move(type_param_bounds)), locus(locus) {} - - // copy constructor with vector clone - TraitObjectType(TraitObjectType const& other) : - has_dyn(other.has_dyn), locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - } - - // overloaded assignment operator to clone - TraitObjectType& operator=(TraitObjectType const& other) { - has_dyn = other.has_dyn; - locus = other.locus; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - type_param_bounds.reserve(other.type_param_bounds.size()); - - for (const auto& e : other.type_param_bounds) { - type_param_bounds.push_back(e->clone_type_param_bound()); - } - - return *this; - } - - // move constructors - TraitObjectType(TraitObjectType&& other) = default; - TraitObjectType& operator=(TraitObjectType&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - // A type with parentheses around it, used to avoid ambiguity. - class ParenthesisedType : public TypeNoBounds { - // Type type_in_parens; - ::std::unique_ptr<Type> type_in_parens; - - Location locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ParenthesisedType* clone_type_impl() const OVERRIDE { - return new ParenthesisedType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ParenthesisedType* clone_type_no_bounds_impl() const OVERRIDE { - return new ParenthesisedType(*this); - } - - public: - // Constructor uses Type pointer for polymorphism - ParenthesisedType(::std::unique_ptr<Type> type_inside_parens, Location locus) : - type_in_parens(::std::move(type_inside_parens)), locus(locus) {} - - // Copy constructor uses custom deep copy method for type to preserve polymorphism - ParenthesisedType(ParenthesisedType const& other) : - type_in_parens(other.type_in_parens->clone_type()), locus(other.locus) {} - - // define destructor here if required - - // overload assignment operator to use custom clone method - ParenthesisedType& operator=(ParenthesisedType const& other) { - type_in_parens = other.type_in_parens->clone_type(); - locus = other.locus; - return *this; - } - - // default move semantics - ParenthesisedType(ParenthesisedType&& other) = default; - ParenthesisedType& operator=(ParenthesisedType&& other) = default; - - ::std::string as_string() const { - return "(" + type_in_parens->as_string() + ")"; - } - - // Creates a trait bound (clone of this one's trait bound) - HACK - virtual TraitBound* to_trait_bound(bool in_parens ATTRIBUTE_UNUSED) const OVERRIDE { - /* NOTE: obviously it is unknown whether the internal type is a trait bound due to - * polymorphism, so just let the internal type handle it. As parenthesised type, it - * must be in parentheses. */ - return type_in_parens->to_trait_bound(true); - } - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - // Impl trait with a single bound? Poor reference material here. - class ImplTraitTypeOneBound : public TypeNoBounds { - TraitBound trait_bound; - - Location locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ImplTraitTypeOneBound* clone_type_impl() const OVERRIDE { - return new ImplTraitTypeOneBound(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ImplTraitTypeOneBound* clone_type_no_bounds_impl() const OVERRIDE { - return new ImplTraitTypeOneBound(*this); - } - - public: - ImplTraitTypeOneBound(TraitBound trait_bound, Location locus) : - trait_bound(::std::move(trait_bound)), locus(locus) {} - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - /* A trait object with a single trait bound. The "trait bound" is really just the trait. - * Basically like using an interface as a type in an OOP language. */ - class TraitObjectTypeOneBound : public TypeNoBounds { - bool has_dyn; - TraitBound trait_bound; - - Location locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TraitObjectTypeOneBound* clone_type_impl() const OVERRIDE { - return new TraitObjectTypeOneBound(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TraitObjectTypeOneBound* clone_type_no_bounds_impl() const OVERRIDE { - return new TraitObjectTypeOneBound(*this); - } - - public: - TraitObjectTypeOneBound( - TraitBound trait_bound, Location locus, bool is_dyn_dispatch = false) : - has_dyn(is_dyn_dispatch), - trait_bound(::std::move(trait_bound)), locus(locus) {} - - ::std::string as_string() const; - - // Creates a trait bound (clone of this one's trait bound) - HACK - virtual TraitBound* to_trait_bound(bool in_parens ATTRIBUTE_UNUSED) const OVERRIDE { - /* NOTE: this assumes there is no dynamic dispatch specified- if there was, this - * cloning would not be required as parsing is unambiguous. */ - return new AST::TraitBound(trait_bound); - } - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - class TypePath; // definition moved to "rust-path.h" - - // A type consisting of the "product" of others (the tuple's elements) in a specific order - class TupleType : public TypeNoBounds { - //::std::vector<Type> elems; - ::std::vector< ::std::unique_ptr<Type> > elems; - - Location locus; - - public: - // Returns whether the tuple type is the unit type, i.e. has no elements. - inline bool is_unit_type() const { - return elems.empty(); - } - - TupleType(::std::vector< ::std::unique_ptr<Type> > elems, Location locus) : - elems(::std::move(elems)), locus(locus) {} - - // copy constructor with vector clone - TupleType(TupleType const& other) : locus(other.locus) { - // crappy vector unique pointer clone - TODO is there a better way of doing this? - elems.reserve(other.elems.size()); - - for (const auto& e : other.elems) { - elems.push_back(e->clone_type()); - } - } - - // overloaded assignment operator to clone - TupleType& operator=(TupleType const& other) { - locus = other.locus; - // crappy vector unique pointer clone - TODO is there a better way of doing this? - elems.reserve(other.elems.size()); - - for (const auto& e : other.elems) { - elems.push_back(e->clone_type()); - } - - return *this; - } - - // move constructors - TupleType(TupleType&& other) = default; - TupleType& operator=(TupleType&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual TupleType* clone_type_impl() const OVERRIDE { - return new TupleType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual TupleType* clone_type_no_bounds_impl() const OVERRIDE { - return new TupleType(*this); - } - }; - - /* A type with no values, representing the result of computations that never complete. - * Expressions of NeverType can be coerced into any other types. Represented as "!". */ - class NeverType : public TypeNoBounds { - Location locus; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual NeverType* clone_type_impl() const OVERRIDE { - return new NeverType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual NeverType* clone_type_no_bounds_impl() const OVERRIDE { - return new NeverType(*this); - } - - public: - NeverType(Location locus) : locus(locus) {} - - ::std::string as_string() const { - return "! (never type)"; - } - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - // A type consisting of a pointer without safety or liveness guarantees - class RawPointerType : public TypeNoBounds { - public: - enum PointerType { MUT, CONST }; - - private: - PointerType pointer_type; - - // TypeNoBounds type; - ::std::unique_ptr<TypeNoBounds> type; - - Location locus; - - public: - // Returns whether the pointer is mutable or constant. - inline PointerType get_pointer_type() const { - return pointer_type; - } - - // Constructor requires pointer for polymorphism reasons - RawPointerType(PointerType pointer_type, ::std::unique_ptr<TypeNoBounds> type_no_bounds, - Location locus) : - pointer_type(pointer_type), - type(::std::move(type_no_bounds)), locus(locus) {} - - // Copy constructor calls custom polymorphic clone function - RawPointerType(RawPointerType const& other) : - pointer_type(other.pointer_type), type(other.type->clone_type_no_bounds()), - locus(other.locus) {} - - // no destructor required? - - // overload assignment operator to use custom clone method - RawPointerType& operator=(RawPointerType const& other) { - pointer_type = other.pointer_type; - type = other.type->clone_type_no_bounds(); - locus = other.locus; - return *this; - } - - // default move semantics - RawPointerType(RawPointerType&& other) = default; - RawPointerType& operator=(RawPointerType&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual RawPointerType* clone_type_impl() const OVERRIDE { - return new RawPointerType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual RawPointerType* clone_type_no_bounds_impl() const OVERRIDE { - return new RawPointerType(*this); - } - }; - - // A type pointing to memory owned by another value - class ReferenceType : public TypeNoBounds { - // bool has_lifetime; // TODO: handle in lifetime or something? - Lifetime lifetime; - - bool has_mut; - - // TypeNoBounds type; - ::std::unique_ptr<TypeNoBounds> type; - - Location locus; - - public: - // Returns whether the reference is mutable or immutable. - inline bool is_mut() const { - return has_mut; - } - - // Returns whether the reference has a lifetime. - inline bool has_lifetime() const { - return !lifetime.is_error(); - } - - // Constructor - ReferenceType(bool is_mut, ::std::unique_ptr<TypeNoBounds> type_no_bounds, Location locus, - Lifetime lifetime = Lifetime::error()) : - lifetime(::std::move(lifetime)), - has_mut(is_mut), type(::std::move(type_no_bounds)), locus(locus) {} - - // Copy constructor with custom clone method - ReferenceType(ReferenceType const& other) : - lifetime(other.lifetime), has_mut(other.has_mut), - type(other.type->clone_type_no_bounds()), locus(other.locus) {} - - // Destructor not required? - - // Operator overload assignment operator to custom clone the unique pointer - ReferenceType& operator=(ReferenceType const& other) { - lifetime = other.lifetime; - has_mut = other.has_mut; - type = other.type->clone_type_no_bounds(); - locus = other.locus; - - return *this; - } - - // move constructors - ReferenceType(ReferenceType&& other) = default; - ReferenceType& operator=(ReferenceType&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ReferenceType* clone_type_impl() const OVERRIDE { - return new ReferenceType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ReferenceType* clone_type_no_bounds_impl() const OVERRIDE { - return new ReferenceType(*this); - } - }; - - // A fixed-size sequence of elements of a specified type - class ArrayType : public TypeNoBounds { - // Type elem_type; - ::std::unique_ptr<Type> elem_type; - // Expr* size; - ::std::unique_ptr<Expr> size; - - Location locus; - - public: - // Constructor requires pointers for polymorphism - ArrayType( - ::std::unique_ptr<Type> type, ::std::unique_ptr<Expr> array_size, Location locus) : - elem_type(::std::move(type)), - size(::std::move(array_size)), locus(locus) {} - - // Copy constructor requires deep copies of both unique pointers - ArrayType(ArrayType const& other) : - elem_type(other.elem_type->clone_type()), size(other.size->clone_expr()), - locus(other.locus) {} - - // destructor not required? - - // Overload assignment operator to deep copy pointers - ArrayType& operator=(ArrayType const& other) { - elem_type = other.elem_type->clone_type(); - size = other.size->clone_expr(); - locus = other.locus; - return *this; - } - - // move constructors - ArrayType(ArrayType&& other) = default; - ArrayType& operator=(ArrayType&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - /*~ArrayType() { - delete size; - }*/ - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayType* clone_type_impl() const OVERRIDE { - return new ArrayType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual ArrayType* clone_type_no_bounds_impl() const OVERRIDE { - return new ArrayType(*this); - } - }; - - // A dynamically-sized type representing a "view" into a sequence of elements of a type - class SliceType : public TypeNoBounds { - // Type elem_type; - ::std::unique_ptr<Type> elem_type; - - Location locus; - - public: - // Constructor requires pointer for polymorphism - SliceType(::std::unique_ptr<Type> type, Location locus) : - elem_type(::std::move(type)), locus(locus) {} - - // Copy constructor requires deep copy of Type smart pointer - SliceType(SliceType const& other) : - elem_type(other.elem_type->clone_type()), locus(other.locus) {} - - // destructor not required? - - // Overload assignment operator to deep copy - SliceType& operator=(SliceType const& other) { - elem_type = other.elem_type->clone_type(); - locus = other.locus; - - return *this; - } - - // move constructors - SliceType(SliceType&& other) = default; - SliceType& operator=(SliceType&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual SliceType* clone_type_impl() const OVERRIDE { - return new SliceType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual SliceType* clone_type_no_bounds_impl() const OVERRIDE { - return new SliceType(*this); - } - }; - - // Type used in generic arguments to explicitly request type inference (wildcard pattern) - class InferredType : public TypeNoBounds { - Location locus; - - // e.g. Vec<_> = whatever - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual InferredType* clone_type_impl() const OVERRIDE { - return new InferredType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual InferredType* clone_type_no_bounds_impl() const OVERRIDE { - return new InferredType(*this); - } - - public: - InferredType(Location locus) : locus(locus) {} - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - }; - - class QualifiedPathInType; // definition moved to "rust-path.h" - - // A possibly named param used in a BaseFunctionType - struct MaybeNamedParam { - public: - enum ParamKind { UNNAMED, IDENTIFIER, WILDCARD }; - - private: - // Type param_type; - ::std::unique_ptr<Type> param_type; - - ParamKind param_kind; - Identifier name; // technically, can be an identifier or '_' - - Location locus; - - public: - MaybeNamedParam(Identifier name, ParamKind param_kind, ::std::unique_ptr<Type> param_type, - Location locus) : - param_type(::std::move(param_type)), - param_kind(param_kind), name(::std::move(name)), locus(locus) {} - - // Copy constructor with clone - MaybeNamedParam(MaybeNamedParam const& other) : - param_type(other.param_type->clone_type()), param_kind(other.param_kind), - name(other.name), locus(other.locus) {} - - ~MaybeNamedParam() = default; - - // Overloaded assignment operator with clone - MaybeNamedParam& operator=(MaybeNamedParam const& other) { - name = other.name; - param_kind = other.param_kind; - param_type = other.param_type->clone_type(); - locus = other.locus; - - return *this; - } - - // move constructors - MaybeNamedParam(MaybeNamedParam&& other) = default; - MaybeNamedParam& operator=(MaybeNamedParam&& other) = default; - - ::std::string as_string() const; - - // Returns whether the param is in an error state. - inline bool is_error() const { - return param_type == NULL; - } - - // Creates an error state param. - static MaybeNamedParam create_error() { - return MaybeNamedParam("", UNNAMED, NULL, Location()); - } - - Location get_locus() const { - return locus; - } - }; - - /* A function pointer type - can be created via coercion from function items and non- - * capturing closures. */ - class BareFunctionType : public TypeNoBounds { - // bool has_for_lifetimes; - // ForLifetimes for_lifetimes; - ::std::vector<LifetimeParam> for_lifetimes; // inlined version - - FunctionQualifiers function_qualifiers; - ::std::vector<MaybeNamedParam> params; - bool is_variadic; - - // bool has_return_type; - // BareFunctionReturnType return_type; - ::std::unique_ptr<TypeNoBounds> return_type; // inlined version - - Location locus; - - public: - // Whether a return type is defined with the function. - inline bool has_return_type() const { - return return_type != NULL; - } - - // Whether the function has ForLifetimes. - inline bool has_for_lifetimes() const { - return !for_lifetimes.empty(); - } - - BareFunctionType(::std::vector<LifetimeParam> lifetime_params, - FunctionQualifiers qualifiers, ::std::vector<MaybeNamedParam> named_params, - bool is_variadic, ::std::unique_ptr<TypeNoBounds> type, Location locus) : - for_lifetimes(::std::move(lifetime_params)), - function_qualifiers(::std::move(qualifiers)), params(::std::move(named_params)), - is_variadic(is_variadic), return_type(::std::move(type)), locus(locus) {} - - // Copy constructor with clone - BareFunctionType(BareFunctionType const& other) : - for_lifetimes(other.for_lifetimes), function_qualifiers(other.function_qualifiers), - params(other.params), is_variadic(other.is_variadic), - return_type(other.return_type->clone_type_no_bounds()), locus(other.locus) {} - - // destructor - define here if required - - // Overload assignment operator to deep copy - BareFunctionType& operator=(BareFunctionType const& other) { - for_lifetimes = other.for_lifetimes; - function_qualifiers = other.function_qualifiers; - params = other.params; - is_variadic = other.is_variadic; - return_type = other.return_type->clone_type_no_bounds(); - locus = other.locus; - - return *this; - } - - // move constructors - BareFunctionType(BareFunctionType&& other) = default; - BareFunctionType& operator=(BareFunctionType&& other) = default; - - ::std::string as_string() const; - - Location get_locus() const { - return locus; - } - - virtual void accept_vis(ASTVisitor& vis) OVERRIDE; - - protected: - // Use covariance to implement clone function as returning this object rather than base - virtual BareFunctionType* clone_type_impl() const OVERRIDE { - return new BareFunctionType(*this); - } - - // Use covariance to implement clone function as returning this object rather than base - virtual BareFunctionType* clone_type_no_bounds_impl() const OVERRIDE { - return new BareFunctionType(*this); - } - }; - - // Forward decl - defined in rust-macro.h - class MacroInvocation; - - /*// AST node of a macro invocation, which is replaced by the macro result at compile time - class MacroInvocation : public TypeNoBounds, public Pattern, public ExprWithoutBlock { - SimplePath path; - DelimTokenTree token_tree; - };*/ - - /* TODO: possible types - * struct type? - * "enum" (tagged union) type? - * C-like union type? - * function item type? - * closure expression types? - * primitive types (bool, int, float, char, str (the slice)) - * Although supposedly TypePaths are used to reference these types (including primitives) */ - - /* FIXME: Incomplete spec references: - * anonymous type parameters, aka "impl Trait in argument position" - impl then trait bounds - * abstract return types, aka "impl Trait in return position" - impl then trait bounds */ - } -} +namespace AST { +// definitions moved to rust-ast.h +class TypeParamBound; +class Lifetime; + +// A trait bound +class TraitBound : public TypeParamBound +{ + bool in_parens; + bool opening_question_mark; + + // bool has_for_lifetimes; + // LifetimeParams for_lifetimes; + ::std::vector<LifetimeParam> for_lifetimes; // inlined LifetimeParams + + TypePath type_path; + + Location locus; + +public: + // Returns whether trait bound has "for" lifetimes + inline bool has_for_lifetimes () const { return !for_lifetimes.empty (); } + + TraitBound (TypePath type_path, Location locus, bool in_parens = false, + bool opening_question_mark = false, + ::std::vector<LifetimeParam> for_lifetimes + = ::std::vector<LifetimeParam> ()) + : in_parens (in_parens), opening_question_mark (opening_question_mark), + for_lifetimes (::std::move (for_lifetimes)), + type_path (::std::move (type_path)), locus (locus) + {} + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Clone function implementation as (not pure) virtual method + virtual TraitBound *clone_type_param_bound_impl () const + { + return new TraitBound (*this); + } +}; + +// definition moved to rust-ast.h +class TypeNoBounds; + +// An impl trait? Poor reference material here. +class ImplTraitType : public Type +{ + // TypeParamBounds type_param_bounds; + ::std::vector< ::std::unique_ptr<TypeParamBound> > + type_param_bounds; // inlined form + + Location locus; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ImplTraitType *clone_type_impl () const OVERRIDE + { + return new ImplTraitType (*this); + } + +public: + ImplTraitType ( + ::std::vector< ::std::unique_ptr<TypeParamBound> > type_param_bounds, + Location locus) + : type_param_bounds (::std::move (type_param_bounds)), locus (locus) + {} + + // copy constructor with vector clone + ImplTraitType (ImplTraitType const &other) : locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + type_param_bounds.reserve (other.type_param_bounds.size ()); + + for (const auto &e : other.type_param_bounds) + { + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + } + + // overloaded assignment operator to clone + ImplTraitType &operator= (ImplTraitType const &other) + { + locus = other.locus; + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + type_param_bounds.reserve (other.type_param_bounds.size ()); + + for (const auto &e : other.type_param_bounds) + { + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + + return *this; + } + + // move constructors + ImplTraitType (ImplTraitType &&other) = default; + ImplTraitType &operator= (ImplTraitType &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; +}; + +// An opaque value of another type that implements a set of traits +class TraitObjectType : public Type +{ + bool has_dyn; + // TypeParamBounds type_param_bounds; + ::std::vector< ::std::unique_ptr<TypeParamBound> > + type_param_bounds; // inlined form + + Location locus; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TraitObjectType *clone_type_impl () const OVERRIDE + { + return new TraitObjectType (*this); + } + +public: + TraitObjectType ( + ::std::vector< ::std::unique_ptr<TypeParamBound> > type_param_bounds, + Location locus, bool is_dyn_dispatch = false) + : has_dyn (is_dyn_dispatch), + type_param_bounds (::std::move (type_param_bounds)), locus (locus) + {} + + // copy constructor with vector clone + TraitObjectType (TraitObjectType const &other) + : has_dyn (other.has_dyn), locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + type_param_bounds.reserve (other.type_param_bounds.size ()); + + for (const auto &e : other.type_param_bounds) + { + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + } + + // overloaded assignment operator to clone + TraitObjectType &operator= (TraitObjectType const &other) + { + has_dyn = other.has_dyn; + locus = other.locus; + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + type_param_bounds.reserve (other.type_param_bounds.size ()); + + for (const auto &e : other.type_param_bounds) + { + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + + return *this; + } + + // move constructors + TraitObjectType (TraitObjectType &&other) = default; + TraitObjectType &operator= (TraitObjectType &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; +}; + +// A type with parentheses around it, used to avoid ambiguity. +class ParenthesisedType : public TypeNoBounds +{ + // Type type_in_parens; + ::std::unique_ptr<Type> type_in_parens; + + Location locus; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ParenthesisedType *clone_type_impl () const OVERRIDE + { + return new ParenthesisedType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ParenthesisedType *clone_type_no_bounds_impl () const OVERRIDE + { + return new ParenthesisedType (*this); + } + +public: + // Constructor uses Type pointer for polymorphism + ParenthesisedType (::std::unique_ptr<Type> type_inside_parens, Location locus) + : type_in_parens (::std::move (type_inside_parens)), locus (locus) + {} + + // Copy constructor uses custom deep copy method for type to preserve + // polymorphism + ParenthesisedType (ParenthesisedType const &other) + : type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus) + {} + + // define destructor here if required + + // overload assignment operator to use custom clone method + ParenthesisedType &operator= (ParenthesisedType const &other) + { + type_in_parens = other.type_in_parens->clone_type (); + locus = other.locus; + return *this; + } + + // default move semantics + ParenthesisedType (ParenthesisedType &&other) = default; + ParenthesisedType &operator= (ParenthesisedType &&other) = default; + + ::std::string as_string () const + { + return "(" + type_in_parens->as_string () + ")"; + } + + // Creates a trait bound (clone of this one's trait bound) - HACK + virtual TraitBound * + to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const OVERRIDE + { + /* NOTE: obviously it is unknown whether the internal type is a trait bound + * due to polymorphism, so just let the internal type handle it. As + * parenthesised type, it must be in parentheses. */ + return type_in_parens->to_trait_bound (true); + } + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; +}; + +// Impl trait with a single bound? Poor reference material here. +class ImplTraitTypeOneBound : public TypeNoBounds +{ + TraitBound trait_bound; + + Location locus; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ImplTraitTypeOneBound *clone_type_impl () const OVERRIDE + { + return new ImplTraitTypeOneBound (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ImplTraitTypeOneBound *clone_type_no_bounds_impl () const OVERRIDE + { + return new ImplTraitTypeOneBound (*this); + } + +public: + ImplTraitTypeOneBound (TraitBound trait_bound, Location locus) + : trait_bound (::std::move (trait_bound)), locus (locus) + {} + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; +}; + +/* A trait object with a single trait bound. The "trait bound" is really just + * the trait. Basically like using an interface as a type in an OOP language. */ +class TraitObjectTypeOneBound : public TypeNoBounds +{ + bool has_dyn; + TraitBound trait_bound; + + Location locus; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TraitObjectTypeOneBound *clone_type_impl () const OVERRIDE + { + return new TraitObjectTypeOneBound (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual TraitObjectTypeOneBound *clone_type_no_bounds_impl () const OVERRIDE + { + return new TraitObjectTypeOneBound (*this); + } + +public: + TraitObjectTypeOneBound (TraitBound trait_bound, Location locus, + bool is_dyn_dispatch = false) + : has_dyn (is_dyn_dispatch), trait_bound (::std::move (trait_bound)), + locus (locus) + {} + + ::std::string as_string () const; + + // Creates a trait bound (clone of this one's trait bound) - HACK + virtual TraitBound * + to_trait_bound (bool in_parens ATTRIBUTE_UNUSED) const OVERRIDE + { + /* NOTE: this assumes there is no dynamic dispatch specified- if there was, + * this cloning would not be required as parsing is unambiguous. */ + return new AST::TraitBound (trait_bound); + } + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; +}; + +class TypePath; // definition moved to "rust-path.h" + +// A type consisting of the "product" of others (the tuple's elements) in a +// specific order +class TupleType : public TypeNoBounds +{ + //::std::vector<Type> elems; + ::std::vector< ::std::unique_ptr<Type> > elems; + + Location locus; + +public: + // Returns whether the tuple type is the unit type, i.e. has no elements. + inline bool is_unit_type () const { return elems.empty (); } + + TupleType (::std::vector< ::std::unique_ptr<Type> > elems, Location locus) + : elems (::std::move (elems)), locus (locus) + {} + + // copy constructor with vector clone + TupleType (TupleType const &other) : locus (other.locus) + { + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + elems.reserve (other.elems.size ()); + + for (const auto &e : other.elems) + { + elems.push_back (e->clone_type ()); + } + } + + // overloaded assignment operator to clone + TupleType &operator= (TupleType const &other) + { + locus = other.locus; + // crappy vector unique pointer clone - TODO is there a better way of doing + // this? + elems.reserve (other.elems.size ()); + + for (const auto &e : other.elems) + { + elems.push_back (e->clone_type ()); + } + + return *this; + } + + // move constructors + TupleType (TupleType &&other) = default; + TupleType &operator= (TupleType &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual TupleType *clone_type_impl () const OVERRIDE + { + return new TupleType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual TupleType *clone_type_no_bounds_impl () const OVERRIDE + { + return new TupleType (*this); + } +}; + +/* A type with no values, representing the result of computations that never + * complete. Expressions of NeverType can be coerced into any other types. + * Represented as "!". */ +class NeverType : public TypeNoBounds +{ + Location locus; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual NeverType *clone_type_impl () const OVERRIDE + { + return new NeverType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual NeverType *clone_type_no_bounds_impl () const OVERRIDE + { + return new NeverType (*this); + } + +public: + NeverType (Location locus) : locus (locus) {} + + ::std::string as_string () const { return "! (never type)"; } + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; +}; + +// A type consisting of a pointer without safety or liveness guarantees +class RawPointerType : public TypeNoBounds +{ +public: + enum PointerType + { + MUT, + CONST + }; + +private: + PointerType pointer_type; + + // TypeNoBounds type; + ::std::unique_ptr<TypeNoBounds> type; + + Location locus; + +public: + // Returns whether the pointer is mutable or constant. + inline PointerType get_pointer_type () const { return pointer_type; } + + // Constructor requires pointer for polymorphism reasons + RawPointerType (PointerType pointer_type, + ::std::unique_ptr<TypeNoBounds> type_no_bounds, + Location locus) + : pointer_type (pointer_type), type (::std::move (type_no_bounds)), + locus (locus) + {} + + // Copy constructor calls custom polymorphic clone function + RawPointerType (RawPointerType const &other) + : pointer_type (other.pointer_type), + type (other.type->clone_type_no_bounds ()), locus (other.locus) + {} + + // no destructor required? + + // overload assignment operator to use custom clone method + RawPointerType &operator= (RawPointerType const &other) + { + pointer_type = other.pointer_type; + type = other.type->clone_type_no_bounds (); + locus = other.locus; + return *this; + } + + // default move semantics + RawPointerType (RawPointerType &&other) = default; + RawPointerType &operator= (RawPointerType &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual RawPointerType *clone_type_impl () const OVERRIDE + { + return new RawPointerType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual RawPointerType *clone_type_no_bounds_impl () const OVERRIDE + { + return new RawPointerType (*this); + } +}; + +// A type pointing to memory owned by another value +class ReferenceType : public TypeNoBounds +{ + // bool has_lifetime; // TODO: handle in lifetime or something? + Lifetime lifetime; + + bool has_mut; + + // TypeNoBounds type; + ::std::unique_ptr<TypeNoBounds> type; + + Location locus; + +public: + // Returns whether the reference is mutable or immutable. + inline bool is_mut () const { return has_mut; } + + // Returns whether the reference has a lifetime. + inline bool has_lifetime () const { return !lifetime.is_error (); } + + // Constructor + ReferenceType (bool is_mut, ::std::unique_ptr<TypeNoBounds> type_no_bounds, + Location locus, Lifetime lifetime = Lifetime::error ()) + : lifetime (::std::move (lifetime)), has_mut (is_mut), + type (::std::move (type_no_bounds)), locus (locus) + {} + + // Copy constructor with custom clone method + ReferenceType (ReferenceType const &other) + : lifetime (other.lifetime), has_mut (other.has_mut), + type (other.type->clone_type_no_bounds ()), locus (other.locus) + {} + + // Destructor not required? + + // Operator overload assignment operator to custom clone the unique pointer + ReferenceType &operator= (ReferenceType const &other) + { + lifetime = other.lifetime; + has_mut = other.has_mut; + type = other.type->clone_type_no_bounds (); + locus = other.locus; + + return *this; + } + + // move constructors + ReferenceType (ReferenceType &&other) = default; + ReferenceType &operator= (ReferenceType &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ReferenceType *clone_type_impl () const OVERRIDE + { + return new ReferenceType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ReferenceType *clone_type_no_bounds_impl () const OVERRIDE + { + return new ReferenceType (*this); + } +}; + +// A fixed-size sequence of elements of a specified type +class ArrayType : public TypeNoBounds +{ + // Type elem_type; + ::std::unique_ptr<Type> elem_type; + // Expr* size; + ::std::unique_ptr<Expr> size; + + Location locus; + +public: + // Constructor requires pointers for polymorphism + ArrayType (::std::unique_ptr<Type> type, ::std::unique_ptr<Expr> array_size, + Location locus) + : elem_type (::std::move (type)), size (::std::move (array_size)), + locus (locus) + {} + + // Copy constructor requires deep copies of both unique pointers + ArrayType (ArrayType const &other) + : elem_type (other.elem_type->clone_type ()), + size (other.size->clone_expr ()), locus (other.locus) + {} + + // destructor not required? + + // Overload assignment operator to deep copy pointers + ArrayType &operator= (ArrayType const &other) + { + elem_type = other.elem_type->clone_type (); + size = other.size->clone_expr (); + locus = other.locus; + return *this; + } + + // move constructors + ArrayType (ArrayType &&other) = default; + ArrayType &operator= (ArrayType &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + + /*~ArrayType() { + delete size; + }*/ +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual ArrayType *clone_type_impl () const OVERRIDE + { + return new ArrayType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual ArrayType *clone_type_no_bounds_impl () const OVERRIDE + { + return new ArrayType (*this); + } +}; + +// A dynamically-sized type representing a "view" into a sequence of elements of +// a type +class SliceType : public TypeNoBounds +{ + // Type elem_type; + ::std::unique_ptr<Type> elem_type; + + Location locus; + +public: + // Constructor requires pointer for polymorphism + SliceType (::std::unique_ptr<Type> type, Location locus) + : elem_type (::std::move (type)), locus (locus) + {} + + // Copy constructor requires deep copy of Type smart pointer + SliceType (SliceType const &other) + : elem_type (other.elem_type->clone_type ()), locus (other.locus) + {} + + // destructor not required? + + // Overload assignment operator to deep copy + SliceType &operator= (SliceType const &other) + { + elem_type = other.elem_type->clone_type (); + locus = other.locus; + + return *this; + } + + // move constructors + SliceType (SliceType &&other) = default; + SliceType &operator= (SliceType &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual SliceType *clone_type_impl () const OVERRIDE + { + return new SliceType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual SliceType *clone_type_no_bounds_impl () const OVERRIDE + { + return new SliceType (*this); + } +}; + +// Type used in generic arguments to explicitly request type inference (wildcard +// pattern) +class InferredType : public TypeNoBounds +{ + Location locus; + + // e.g. Vec<_> = whatever +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual InferredType *clone_type_impl () const OVERRIDE + { + return new InferredType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual InferredType *clone_type_no_bounds_impl () const OVERRIDE + { + return new InferredType (*this); + } + +public: + InferredType (Location locus) : locus (locus) {} + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; +}; + +class QualifiedPathInType; // definition moved to "rust-path.h" + +// A possibly named param used in a BaseFunctionType +struct MaybeNamedParam +{ +public: + enum ParamKind + { + UNNAMED, + IDENTIFIER, + WILDCARD + }; + +private: + // Type param_type; + ::std::unique_ptr<Type> param_type; + + ParamKind param_kind; + Identifier name; // technically, can be an identifier or '_' + + Location locus; + +public: + MaybeNamedParam (Identifier name, ParamKind param_kind, + ::std::unique_ptr<Type> param_type, Location locus) + : param_type (::std::move (param_type)), param_kind (param_kind), + name (::std::move (name)), locus (locus) + {} + + // Copy constructor with clone + MaybeNamedParam (MaybeNamedParam const &other) + : param_type (other.param_type->clone_type ()), + param_kind (other.param_kind), name (other.name), locus (other.locus) + {} + + ~MaybeNamedParam () = default; + + // Overloaded assignment operator with clone + MaybeNamedParam &operator= (MaybeNamedParam const &other) + { + name = other.name; + param_kind = other.param_kind; + param_type = other.param_type->clone_type (); + locus = other.locus; + + return *this; + } + + // move constructors + MaybeNamedParam (MaybeNamedParam &&other) = default; + MaybeNamedParam &operator= (MaybeNamedParam &&other) = default; + + ::std::string as_string () const; + + // Returns whether the param is in an error state. + inline bool is_error () const { return param_type == NULL; } + + // Creates an error state param. + static MaybeNamedParam create_error () + { + return MaybeNamedParam ("", UNNAMED, NULL, Location ()); + } + + Location get_locus () const { return locus; } +}; + +/* A function pointer type - can be created via coercion from function items and + * non- capturing closures. */ +class BareFunctionType : public TypeNoBounds +{ + // bool has_for_lifetimes; + // ForLifetimes for_lifetimes; + ::std::vector<LifetimeParam> for_lifetimes; // inlined version + + FunctionQualifiers function_qualifiers; + ::std::vector<MaybeNamedParam> params; + bool is_variadic; + + // bool has_return_type; + // BareFunctionReturnType return_type; + ::std::unique_ptr<TypeNoBounds> return_type; // inlined version + + Location locus; + +public: + // Whether a return type is defined with the function. + inline bool has_return_type () const { return return_type != NULL; } + + // Whether the function has ForLifetimes. + inline bool has_for_lifetimes () const { return !for_lifetimes.empty (); } + + BareFunctionType (::std::vector<LifetimeParam> lifetime_params, + FunctionQualifiers qualifiers, + ::std::vector<MaybeNamedParam> named_params, + bool is_variadic, ::std::unique_ptr<TypeNoBounds> type, + Location locus) + : for_lifetimes (::std::move (lifetime_params)), + function_qualifiers (::std::move (qualifiers)), + params (::std::move (named_params)), is_variadic (is_variadic), + return_type (::std::move (type)), locus (locus) + {} + + // Copy constructor with clone + BareFunctionType (BareFunctionType const &other) + : for_lifetimes (other.for_lifetimes), + function_qualifiers (other.function_qualifiers), params (other.params), + is_variadic (other.is_variadic), + return_type (other.return_type->clone_type_no_bounds ()), + locus (other.locus) + {} + + // destructor - define here if required + + // Overload assignment operator to deep copy + BareFunctionType &operator= (BareFunctionType const &other) + { + for_lifetimes = other.for_lifetimes; + function_qualifiers = other.function_qualifiers; + params = other.params; + is_variadic = other.is_variadic; + return_type = other.return_type->clone_type_no_bounds (); + locus = other.locus; + + return *this; + } + + // move constructors + BareFunctionType (BareFunctionType &&other) = default; + BareFunctionType &operator= (BareFunctionType &&other) = default; + + ::std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (ASTVisitor &vis) OVERRIDE; + +protected: + // Use covariance to implement clone function as returning this object rather + // than base + virtual BareFunctionType *clone_type_impl () const OVERRIDE + { + return new BareFunctionType (*this); + } + + // Use covariance to implement clone function as returning this object rather + // than base + virtual BareFunctionType *clone_type_no_bounds_impl () const OVERRIDE + { + return new BareFunctionType (*this); + } +}; + +// Forward decl - defined in rust-macro.h +class MacroInvocation; + +/*// AST node of a macro invocation, which is replaced by the macro result at +compile time class MacroInvocation : public TypeNoBounds, public Pattern, public +ExprWithoutBlock { SimplePath path; DelimTokenTree token_tree; +};*/ + +/* TODO: possible types + * struct type? + * "enum" (tagged union) type? + * C-like union type? + * function item type? + * closure expression types? + * primitive types (bool, int, float, char, str (the slice)) + * Although supposedly TypePaths are used to reference these types (including + * primitives) */ + +/* FIXME: Incomplete spec references: + * anonymous type parameters, aka "impl Trait in argument position" - impl then + * trait bounds abstract return types, aka "impl Trait in return position" - + * impl then trait bounds */ +} // namespace AST +} // namespace Rust #endif diff --git a/gcc/rust/expand/rust-macro-expand.cc b/gcc/rust/expand/rust-macro-expand.cc index 613d94f..5e5f8fe 100644 --- a/gcc/rust/expand/rust-macro-expand.cc +++ b/gcc/rust/expand/rust-macro-expand.cc @@ -3,67 +3,83 @@ // is full really required? namespace Rust { - void MacroExpander::expand_invoc(::std::unique_ptr<AST::MacroInvocation>& invoc) { - // if current expansion depth > recursion limit, create an error (maybe fatal error) and return - - /* switch on type of macro: - - '!' syntax macro (inner switch) - - procedural macro - "A token-based function-like macro" - - 'macro_rules' (by example/pattern-match) macro? or not? "an AST-based function-like macro" - - else is unreachable - - attribute syntax macro (inner switch) - - procedural macro attribute syntax - "A token-based attribute macro" - - legacy macro attribute syntax? - "an AST-based attribute macro" - - non-macro attribute: mark known - - else is unreachable - - derive macro (inner switch) - - derive or legacy derive - "token-based" vs "AST-based" - - else is unreachable - - derive container macro - unreachable*/ - - } - - // Determines whether cfg predicate is true and item with attribute should not be stripped. - bool check_cfg_predicate() {} - - // Determines whether cfg predicate is true and item with attribute should not be stripped. - bool check_cfg(AST::Attribute& attr) { - +void +MacroExpander::expand_invoc (::std::unique_ptr<AST::MacroInvocation> &invoc) +{ + // if current expansion depth > recursion limit, create an error (maybe fatal + // error) and return + + /* switch on type of macro: + - '!' syntax macro (inner switch) + - procedural macro - "A token-based function-like macro" + - 'macro_rules' (by example/pattern-match) macro? or not? "an + AST-based function-like macro" + - else is unreachable + - attribute syntax macro (inner switch) + - procedural macro attribute syntax - "A token-based attribute macro" + - legacy macro attribute syntax? - "an AST-based attribute macro" + - non-macro attribute: mark known + - else is unreachable + - derive macro (inner switch) + - derive or legacy derive - "token-based" vs "AST-based" + - else is unreachable + - derive container macro - unreachable*/ +} + +// Determines whether cfg predicate is true and item with attribute should not +// be stripped. +bool +check_cfg_predicate () +{} + +// Determines whether cfg predicate is true and item with attribute should not +// be stripped. +bool +check_cfg (AST::Attribute &attr) +{} + +// Expands cfg_attr attributes. +void +expand_attrs_cfgattr (::std::vector<AST::Attribute> &attrs) +{ + for (auto it = attrs.begin (); it != attrs.end ();) + { + auto &attr = *it; + if (attr.get_path () == "cfg_attr") + { + if (check_cfg (attr)) + { + } + + /* do something - if feature (first token in tree) is in fact enabled, + * make tokens listed afterwards into attributes. i.e.: for + * [cfg_attr(feature = "wow", wow1, wow2)], if "wow" is true, then add + * attributes [wow1] and [wow2] to attribute list. This can also be + * recursive, so check for expanded attributes being recursive and + * possibly recursively call the expand_attrs? */ + } + else + { + ++it; + } } +} - // Expands cfg_attr attributes. - void expand_attrs_cfgattr(::std::vector<AST::Attribute>& attrs) { - for (auto it = attrs.begin(); it != attrs.end(); ) { - auto& attr = *it; - if (attr.get_path() == "cfg_attr") { - if (check_cfg(attr)) {} +void +MacroExpander::expand_crate (AST::Crate &crate) +{ + // fill macro/decorator map from init list? not sure where init list comes + // from? - /* do something - if feature (first token in tree) is in fact enabled, make tokens listed - * afterwards into attributes. - * i.e.: for [cfg_attr(feature = "wow", wow1, wow2)], if "wow" is true, then add attributes - * [wow1] and [wow2] to attribute list. - * This can also be recursive, so check for expanded attributes being recursive and - * possibly recursively call the expand_attrs? */ - } else { - ++it; - } - } - } - - void MacroExpander::expand_crate(AST::Crate& crate) { - // fill macro/decorator map from init list? not sure where init list comes from? - - // expand crate attributes - expand_attrs_cfgattr(crate.inner_attrs); + // expand crate attributes + expand_attrs_cfgattr (crate.inner_attrs); - // expand module attributes? + // expand module attributes? - // expand module tree recursively + // expand module tree recursively - // post-process + // post-process - // extract exported macros? - - - } -}
\ No newline at end of file + // extract exported macros? +} +} // namespace Rust diff --git a/gcc/rust/expand/rust-macro-expand.h b/gcc/rust/expand/rust-macro-expand.h index a252a41..543c76f 100644 --- a/gcc/rust/expand/rust-macro-expand.h +++ b/gcc/rust/expand/rust-macro-expand.h @@ -6,42 +6,46 @@ // Provides objects and method prototypes for macro expansion namespace Rust { - // forward decls for AST - namespace AST { - class MacroInvocation; - } - - // Object used to store configuration data for macro expansion. - struct ExpansionCfg { - // features? - unsigned int recursion_limit; // TODO: determine default recursion limit - // trace macros? - // should test? - // more default stuff? - }; - - // Object used to store shared data (between functions) for macro expansion. - struct MacroExpander { - ExpansionCfg cfg; - unsigned int expansion_depth = 0; - - MacroExpander(AST::Crate& crate, ExpansionCfg cfg) : cfg(cfg), crate(crate) {} - - ~MacroExpander() = default; - - // Expands all macros in the crate passed in. - void expand_crate(AST::Crate& crate); - - /* Expands a macro invocation (not macro invocation semi) - possibly make both have similar - * duck-typed interface and use templates?*/ - // should this be public or private? - void expand_invoc(::std::unique_ptr<AST::MacroInvocation>& invoc); - - // TODO: make it extend ASTVisitor so that individual items can be accessed properly? - - private: - AST::Crate& crate; - }; +// forward decls for AST +namespace AST { +class MacroInvocation; } -#endif
\ No newline at end of file +// Object used to store configuration data for macro expansion. +struct ExpansionCfg +{ + // features? + unsigned int recursion_limit; // TODO: determine default recursion limit + // trace macros? + // should test? + // more default stuff? +}; + +// Object used to store shared data (between functions) for macro expansion. +struct MacroExpander +{ + ExpansionCfg cfg; + unsigned int expansion_depth = 0; + + MacroExpander (AST::Crate &crate, ExpansionCfg cfg) : cfg (cfg), crate (crate) + {} + + ~MacroExpander () = default; + + // Expands all macros in the crate passed in. + void expand_crate (AST::Crate &crate); + + /* Expands a macro invocation (not macro invocation semi) - possibly make both + * have similar duck-typed interface and use templates?*/ + // should this be public or private? + void expand_invoc (::std::unique_ptr<AST::MacroInvocation> &invoc); + + // TODO: make it extend ASTVisitor so that individual items can be accessed + // properly? + +private: + AST::Crate &crate; +}; +} // namespace Rust + +#endif diff --git a/gcc/rust/lang-specs.h b/gcc/rust/lang-specs.h index 513e951..bfd4dda 100644 --- a/gcc/rust/lang-specs.h +++ b/gcc/rust/lang-specs.h @@ -1,21 +1,21 @@ /* lang-specs.h -- gcc driver specs for Rust frontend. - Copyright (C) 2009-2019 Free Software Foundation, Inc. + Copyright (C) 2009-2020 Free Software Foundation, Inc. -This file is part of GCC. + 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 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. + 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/>. */ + 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/>. */ /* This is the contribution to the `default_compilers' array in gcc.c for the Rust language. */ diff --git a/gcc/rust/lex/rust-codepoint.h b/gcc/rust/lex/rust-codepoint.h index a00edb3..0f2e5bd 100644 --- a/gcc/rust/lex/rust-codepoint.h +++ b/gcc/rust/lex/rust-codepoint.h @@ -9,18 +9,19 @@ #include <string> namespace Rust { - struct Codepoint { - uint32_t value; +struct Codepoint +{ + uint32_t value; - // Creates a zero codepoint. - Codepoint() : value(0) {} + // Creates a zero codepoint. + Codepoint () : value (0) {} - // Creates a codepoint from UTF-8 value. - Codepoint(uint32_t value_) : value(value_) {} + // Creates a codepoint from UTF-8 value. + Codepoint (uint32_t value_) : value (value_) {} - // Returns a C++ string containing value of codepoint. - ::std::string as_string(); - }; -} + // Returns a C++ string containing value of codepoint. + ::std::string as_string (); +}; +} // namespace Rust -#endif
\ No newline at end of file +#endif diff --git a/gcc/rust/lex/rust-lex.h b/gcc/rust/lex/rust-lex.h index a705367..8dc3e31 100644 --- a/gcc/rust/lex/rust-lex.h +++ b/gcc/rust/lex/rust-lex.h @@ -6,127 +6,131 @@ #include "rust-token.h" namespace Rust { - class Lexer { - private: - // Request new Location for current column in line_table - Location get_current_location(); - - // Skips the current input char. - void skip_input(); - // Advances current input char to n + 1 chars ahead of current position. - void skip_input(int n); - - // Returns char n chars ahead of current position. - int peek_input(); - // Peeks the current char. - int peek_input(int n); - - // Classifies keyword (i.e. gets id for keyword). - TokenId classify_keyword(const std::string& str); - - // Builds a token from the input queue. - TokenPtr build_token(); - - // ok maybe all these may mean the lexer structure needs to be rethought - /* separated into functions because main method was too long, but they rely on and change - * state in the lexer, so variables must be passed by reference. */ - inline void parse_in_decimal(/*char& current_char, */ std::string& str, int& length); - inline void parse_in_exponent_part(/*char& current_char, */ std::string& str, int& length); - inline bool parse_in_type_suffix( - /*char& current_char, */ PrimitiveCoreType& type_hint, int& length); - inline bool parse_ascii_escape(/*char& current_char, */ int& length, char& output_char); - inline bool parse_quote_escape(/*char& current_char, */ int& length, char& output_char); - inline bool parse_unicode_escape( - /*char& current_char, */ int& length, Codepoint& output_char); - inline bool parse_byte_escape(/*char& current_char, */ int& length, char& output_char); - inline bool parse_escape(int& length, char& output_char, char opening_char); - inline bool parse_utf8_escape(int& length, Codepoint& output_char, char opening_char); - inline int test_get_input_codepoint_length(); - inline int test_get_input_codepoint_n_length(int n_start_offset); - inline Codepoint test_peek_codepoint_input(); - inline Codepoint test_peek_codepoint_input( - int n); // maybe can use get_input_codepoint_length to get starting index - inline void test_skip_codepoint_input(); - - public: - // Construct lexer with input file and filename provided - Lexer(const char* filename, FILE* input, Linemap* linemap); - ~Lexer(); - - // Returns token n tokens ahead of current position. - const_TokenPtr peek_token(int n); - // Peeks the current token. - const_TokenPtr peek_token(); - - // Advances current token to n + 1 tokens ahead of current position. - void skip_token(int n); - // Skips the current token. - void skip_token(); - - // Replaces the current token with a specified token. - void replace_current_token(TokenPtr replacement); - - Linemap* get_line_map() { - return line_map; - } - - private: - // File for use as input. - FILE* input; - - // Current line number. - int current_line; - // Current column number. - int current_column; - // Line map. - Linemap* line_map; - - // Max column number that can be quickly allocated - higher may require allocating new linemap - static const int max_column_hint = 80; - - // Input source wrapper thing. - struct InputSource { - // Input source file. - FILE* input; - - // Create new input source from file. - InputSource(FILE* input) : input(input) {} - - // Overload operator () to return next char from input stream. - int operator()() { - return fgetc(input); - } - }; - - // The input source for the lexer. - InputSource input_source; - // Input file queue. - buffered_queue<int, InputSource> input_queue; - - // Token source wrapper thing. - struct TokenSource { - // The lexer object that will use this TokenSource. - Lexer* lexer; - - // Create a new TokenSource with given lexer. - TokenSource(Lexer* parLexer) : lexer(parLexer) {} - - // Overload operator () to build token in lexer. - TokenPtr operator()() { - return lexer->build_token(); - } - }; - - // The token source for the lexer. - TokenSource token_source; - // Token stream queue. - buffered_queue<std::shared_ptr<Token>, TokenSource> token_queue; - - // START CRAPPY CHANGES - int current_char; - - // END CRAPPY CHANGES - }; -} +class Lexer +{ +private: + // Request new Location for current column in line_table + Location get_current_location (); + + // Skips the current input char. + void skip_input (); + // Advances current input char to n + 1 chars ahead of current position. + void skip_input (int n); + + // Returns char n chars ahead of current position. + int peek_input (); + // Peeks the current char. + int peek_input (int n); + + // Classifies keyword (i.e. gets id for keyword). + TokenId classify_keyword (const std::string &str); + + // Builds a token from the input queue. + TokenPtr build_token (); + + // ok maybe all these may mean the lexer structure needs to be rethought + /* separated into functions because main method was too long, but they rely on + * and change state in the lexer, so variables must be passed by reference. */ + inline void parse_in_decimal (/*char& current_char, */ std::string &str, + int &length); + inline void parse_in_exponent_part (/*char& current_char, */ std::string &str, + int &length); + inline bool parse_in_type_suffix ( + /*char& current_char, */ PrimitiveCoreType &type_hint, int &length); + inline bool parse_ascii_escape (/*char& current_char, */ int &length, + char &output_char); + inline bool parse_quote_escape (/*char& current_char, */ int &length, + char &output_char); + inline bool parse_unicode_escape ( + /*char& current_char, */ int &length, Codepoint &output_char); + inline bool parse_byte_escape (/*char& current_char, */ int &length, + char &output_char); + inline bool parse_escape (int &length, char &output_char, char opening_char); + inline bool parse_utf8_escape (int &length, Codepoint &output_char, + char opening_char); + inline int test_get_input_codepoint_length (); + inline int test_get_input_codepoint_n_length (int n_start_offset); + inline Codepoint test_peek_codepoint_input (); + inline Codepoint test_peek_codepoint_input ( + int n); // maybe can use get_input_codepoint_length to get starting index + inline void test_skip_codepoint_input (); + +public: + // Construct lexer with input file and filename provided + Lexer (const char *filename, FILE *input, Linemap *linemap); + ~Lexer (); + + // Returns token n tokens ahead of current position. + const_TokenPtr peek_token (int n); + // Peeks the current token. + const_TokenPtr peek_token (); + + // Advances current token to n + 1 tokens ahead of current position. + void skip_token (int n); + // Skips the current token. + void skip_token (); + + // Replaces the current token with a specified token. + void replace_current_token (TokenPtr replacement); + + Linemap *get_line_map () { return line_map; } + +private: + // File for use as input. + FILE *input; + + // Current line number. + int current_line; + // Current column number. + int current_column; + // Line map. + Linemap *line_map; + + // Max column number that can be quickly allocated - higher may require + // allocating new linemap + static const int max_column_hint = 80; + + // Input source wrapper thing. + struct InputSource + { + // Input source file. + FILE *input; + + // Create new input source from file. + InputSource (FILE *input) : input (input) {} + + // Overload operator () to return next char from input stream. + int operator() () { return fgetc (input); } + }; + + // The input source for the lexer. + InputSource input_source; + // Input file queue. + buffered_queue<int, InputSource> input_queue; + + // Token source wrapper thing. + struct TokenSource + { + // The lexer object that will use this TokenSource. + Lexer *lexer; + + // Create a new TokenSource with given lexer. + TokenSource (Lexer *parLexer) : lexer (parLexer) {} + + // Overload operator () to build token in lexer. + TokenPtr operator() () { return lexer->build_token (); } + }; + + // The token source for the lexer. + TokenSource token_source; + // Token stream queue. + buffered_queue<std::shared_ptr<Token>, TokenSource> token_queue; + + // START CRAPPY CHANGES + int current_char; + + // END CRAPPY CHANGES +}; +} // namespace Rust #endif diff --git a/gcc/rust/lex/rust-token.cc b/gcc/rust/lex/rust-token.cc index 4b71dd8..d8bd661 100644 --- a/gcc/rust/lex/rust-token.cc +++ b/gcc/rust/lex/rust-token.cc @@ -3,98 +3,114 @@ #include "rust-diagnostics.h" // for error_at namespace Rust { - // Hackily defined way to get token description for enum value using x-macros - const char* get_token_description(TokenId id) { - switch (id) { -#define RS_TOKEN(name, descr) \ - case name: \ - return descr; -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) - RS_TOKEN_LIST +// Hackily defined way to get token description for enum value using x-macros +const char * +get_token_description (TokenId id) +{ + switch (id) + { +#define RS_TOKEN(name, descr) \ + case name: \ + return descr; +#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y) + RS_TOKEN_LIST #undef RS_TOKEN_KEYWORD #undef RS_TOKEN - default: - gcc_unreachable(); - } + default: + gcc_unreachable (); } +} - // Hackily defined way to get token description as a string for enum value using x-macros - const char* token_id_to_str(TokenId id) { - switch (id) { -#define RS_TOKEN(name, _) \ - case name: \ - return #name; -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) - RS_TOKEN_LIST +// Hackily defined way to get token description as a string for enum value using +// x-macros +const char * +token_id_to_str (TokenId id) +{ + switch (id) + { +#define RS_TOKEN(name, _) \ + case name: \ + return #name; +#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y) + RS_TOKEN_LIST #undef RS_TOKEN_KEYWORD #undef RS_TOKEN - default: - gcc_unreachable(); - } + default: + gcc_unreachable (); } +} - const char* get_type_hint_string(PrimitiveCoreType type) { - switch (type) { - case CORETYPE_BOOL: - return "bool"; - case CORETYPE_CHAR: - return "char"; - case CORETYPE_STR: - return "str"; - // case CORETYPE_INT: - case CORETYPE_ISIZE: - return "isize"; - // case CORETYPE_UINT: - case CORETYPE_USIZE: - return "usize"; - case CORETYPE_F32: - return "f32"; - case CORETYPE_F64: - return "f64"; - case CORETYPE_I8: - return "i8"; - case CORETYPE_I16: - return "i16"; - case CORETYPE_I32: - return "i32"; - case CORETYPE_I64: - return "i64"; - case CORETYPE_I128: - return "i128"; - case CORETYPE_U8: - return "u8"; - case CORETYPE_U16: - return "u16"; - case CORETYPE_U32: - return "u32"; - case CORETYPE_U64: - return "u64"; - case CORETYPE_U128: - return "u128"; - case CORETYPE_UNKNOWN: - default: - return "unknown"; - } +const char * +get_type_hint_string (PrimitiveCoreType type) +{ + switch (type) + { + case CORETYPE_BOOL: + return "bool"; + case CORETYPE_CHAR: + return "char"; + case CORETYPE_STR: + return "str"; + // case CORETYPE_INT: + case CORETYPE_ISIZE: + return "isize"; + // case CORETYPE_UINT: + case CORETYPE_USIZE: + return "usize"; + case CORETYPE_F32: + return "f32"; + case CORETYPE_F64: + return "f64"; + case CORETYPE_I8: + return "i8"; + case CORETYPE_I16: + return "i16"; + case CORETYPE_I32: + return "i32"; + case CORETYPE_I64: + return "i64"; + case CORETYPE_I128: + return "i128"; + case CORETYPE_U8: + return "u8"; + case CORETYPE_U16: + return "u16"; + case CORETYPE_U32: + return "u32"; + case CORETYPE_U64: + return "u64"; + case CORETYPE_U128: + return "u128"; + case CORETYPE_UNKNOWN: + default: + return "unknown"; } +} - const char* Token::get_type_hint_str() const { - return get_type_hint_string(type_hint); - } +const char * +Token::get_type_hint_str () const +{ + return get_type_hint_string (type_hint); +} - const ::std::string& Token::get_str() const { - // FIXME: attempt to return null again - // gcc_assert(str != NULL); +const ::std::string & +Token::get_str () const +{ + // FIXME: attempt to return null again + // gcc_assert(str != NULL); - // HACK: allow referencing an empty string - static const ::std::string empty = ""; + // HACK: allow referencing an empty string + static const ::std::string empty = ""; - if (str == NULL) { - rust_error_at(get_locus(), - "attempted to get string for '%s', which has no string. returning empty string " - "instead.", - get_token_description()); - return empty; - } - return *str; + if (str == NULL) + { + rust_error_at (get_locus (), + "attempted to get string for '%s', which has no string. " + "returning empty string " + "instead.", + get_token_description ()); + return empty; } + return *str; } +} // namespace Rust diff --git a/gcc/rust/lex/rust-token.h b/gcc/rust/lex/rust-token.h index 13f4a18..2270fa2 100644 --- a/gcc/rust/lex/rust-token.h +++ b/gcc/rust/lex/rust-token.h @@ -16,371 +16,402 @@ #include "rust-codepoint.h" namespace Rust { - // "Primitive core types" in Rust - the different int and float types, as well as some others - enum PrimitiveCoreType { - CORETYPE_UNKNOWN, - // named primitives - CORETYPE_BOOL, - CORETYPE_CHAR, - CORETYPE_STR, - // okay technically int and uint are arch-dependent (pointer size) - CORETYPE_INT, - CORETYPE_UINT, - // numbered number primitives - CORETYPE_F32, - CORETYPE_F64, - CORETYPE_I8, - CORETYPE_I16, - CORETYPE_I32, - CORETYPE_I64, - CORETYPE_I128, - CORETYPE_U8, - CORETYPE_U16, - CORETYPE_U32, - CORETYPE_U64, - CORETYPE_U128, - // arch-dependent pointer sizes - CORETYPE_ISIZE = CORETYPE_INT, - CORETYPE_USIZE = CORETYPE_UINT - }; +// "Primitive core types" in Rust - the different int and float types, as well +// as some others +enum PrimitiveCoreType +{ + CORETYPE_UNKNOWN, + // named primitives + CORETYPE_BOOL, + CORETYPE_CHAR, + CORETYPE_STR, + // okay technically int and uint are arch-dependent (pointer size) + CORETYPE_INT, + CORETYPE_UINT, + // numbered number primitives + CORETYPE_F32, + CORETYPE_F64, + CORETYPE_I8, + CORETYPE_I16, + CORETYPE_I32, + CORETYPE_I64, + CORETYPE_I128, + CORETYPE_U8, + CORETYPE_U16, + CORETYPE_U32, + CORETYPE_U64, + CORETYPE_U128, + // arch-dependent pointer sizes + CORETYPE_ISIZE = CORETYPE_INT, + CORETYPE_USIZE = CORETYPE_UINT +}; // RS_TOKEN(name, description) // RS_TOKEN_KEYWORD(name, identifier) // // Keep RS_TOKEN_KEYWORD sorted -// note that abstract, async, become, box, do, final, macro, override, priv, try, typeof, unsized, -// virtual, and yield are unused +// note that abstract, async, become, box, do, final, macro, override, priv, +// try, typeof, unsized, virtual, and yield are unused // TODO finish converting to rust keywords -#define RS_TOKEN_LIST \ - RS_TOKEN(FIRST_TOKEN, "<first-token-marker>") \ - RS_TOKEN(END_OF_FILE, "end of file") \ - RS_TOKEN(EXCLAM, "!") \ - RS_TOKEN(NOT_EQUAL, "!=") \ - RS_TOKEN(PERCENT, "%") \ - RS_TOKEN(PERCENT_EQ, "%=") \ - RS_TOKEN(AMP, "&") \ - RS_TOKEN(AMP_EQ, "&=") \ - RS_TOKEN(LOGICAL_AND, "&&") \ - RS_TOKEN(ASTERISK, "*") \ - RS_TOKEN(ASTERISK_EQ, "*=") \ - RS_TOKEN(PLUS, "+") \ - RS_TOKEN(PLUS_EQ, "+=") \ - RS_TOKEN(COMMA, ",") \ - RS_TOKEN(MINUS, "-") \ - RS_TOKEN(MINUS_EQ, "-=") \ - RS_TOKEN(RETURN_TYPE, "->") \ - RS_TOKEN(DOT, ".") \ - RS_TOKEN(DOT_DOT, "..") \ - RS_TOKEN(DOT_DOT_EQ, "..=") \ - RS_TOKEN(ELLIPSIS, "...") \ - RS_TOKEN(DIV, "/") \ - RS_TOKEN(DIV_EQ, "/=") \ - RS_TOKEN(COLON, ":") \ - RS_TOKEN(SEMICOLON, ";") \ - RS_TOKEN(LEFT_SHIFT, "<<") \ - RS_TOKEN(LEFT_SHIFT_EQ, "<<=") \ - RS_TOKEN(LEFT_ANGLE, "<") \ - RS_TOKEN(LESS_OR_EQUAL, "<=") \ - RS_TOKEN(EQUAL, "=") \ - RS_TOKEN(EQUAL_EQUAL, "==") \ - RS_TOKEN(MATCH_ARROW, "=>") \ - RS_TOKEN(RIGHT_ANGLE, ">") \ - RS_TOKEN(GREATER_OR_EQUAL, ">=") \ - RS_TOKEN(RIGHT_SHIFT, ">>") \ - RS_TOKEN(RIGHT_SHIFT_EQ, ">>=") \ - RS_TOKEN(PATTERN_BIND, "@") \ - RS_TOKEN(TILDE, "~") \ - RS_TOKEN(BACKSLASH, "\\") \ - RS_TOKEN(BACKTICK, "`") \ - RS_TOKEN(CARET, "^") \ - RS_TOKEN(CARET_EQ, "^=") \ - RS_TOKEN(PIPE, "|") \ - RS_TOKEN(PIPE_EQ, "|=") \ - RS_TOKEN(OR, "||") \ - RS_TOKEN(QUESTION_MARK, "?") \ - RS_TOKEN(HASH, "#") \ - /* from here on, dodgy and may not be correct. not operators and may be symbols */ \ - /* RS_TOKEN(SPACE, " ") probably too dodgy */ \ - /* RS_TOKEN(NEWLINE, "\n")*/ \ - RS_TOKEN(SCOPE_RESOLUTION, "::") /* dodgy */ \ - RS_TOKEN(SINGLE_QUOTE, "'") /* should i differentiate from lifetime? */ \ - RS_TOKEN(DOUBLE_QUOTE, "\"") \ - RS_TOKEN(UNDERSCORE, "_") /* TODO: treat as reserved word like mrustc instead? */ \ - RS_TOKEN(IDENTIFIER, "identifier") \ - RS_TOKEN(INT_LITERAL, \ - "integer literal") /* do different int and float types need different literal types? */ \ - RS_TOKEN(FLOAT_LITERAL, "float literal") \ - RS_TOKEN(STRING_LITERAL, "string literal") \ - RS_TOKEN(CHAR_LITERAL, "character literal") \ - RS_TOKEN(BYTE_STRING_LITERAL, "byte string literal") \ - RS_TOKEN(BYTE_CHAR_LITERAL, "byte character literal") \ - RS_TOKEN(LIFETIME, "lifetime") /* TODO: improve token type */ \ - /* Have "interpolated" tokens (whatever that means)? identifer, path, type, pattern, */ \ - /* expression, statement, block, meta, item in mrustc (but not directly in lexer). */ \ - RS_TOKEN(LEFT_PAREN, "(") \ - RS_TOKEN(RIGHT_PAREN, ")") \ - RS_TOKEN(LEFT_CURLY, "{") \ - RS_TOKEN(RIGHT_CURLY, "}") \ - RS_TOKEN(LEFT_SQUARE, "[") \ - RS_TOKEN(RIGHT_SQUARE, "]") \ - /* Macros */ \ - RS_TOKEN(DOLLAR_SIGN, "$") \ - /* Comments */ \ - RS_TOKEN(LINE_COMMENT, "//") \ - RS_TOKEN(INNER_LINE_DOC, "//!") \ - RS_TOKEN(OUTER_LINE_DOC, "///") \ - RS_TOKEN(BLOCK_COMMENT_START, "/*") \ - RS_TOKEN(BLOCK_COMMENT_END, "*/") \ - RS_TOKEN(INNER_BLOCK_DOC_START, "/*!") \ - RS_TOKEN(OUTER_BLOCK_DOC_START, "/**") /* have "weak" union and 'static keywords? */ \ - \ - RS_TOKEN_KEYWORD(ABSTRACT, "abstract") /* unused */ \ - RS_TOKEN_KEYWORD(AS, "as") \ - RS_TOKEN_KEYWORD(ASYNC, "async") /* unused */ \ - RS_TOKEN_KEYWORD(BECOME, "become") /* unused */ \ - RS_TOKEN_KEYWORD(BOX, "box") /* unused */ \ - RS_TOKEN_KEYWORD(BREAK, "break") \ - RS_TOKEN_KEYWORD(CONST, "const") \ - RS_TOKEN_KEYWORD(CONTINUE, "continue") \ - RS_TOKEN_KEYWORD(CRATE, "crate") \ - RS_TOKEN_KEYWORD(DO, "do") /* unused */ \ - RS_TOKEN_KEYWORD(DYN, "dyn") \ - RS_TOKEN_KEYWORD(ELSE, "else") \ - RS_TOKEN_KEYWORD(ENUM_TOK, "enum") \ - RS_TOKEN_KEYWORD(EXTERN_TOK, "extern") \ - RS_TOKEN_KEYWORD(FALSE_LITERAL, "false") \ - RS_TOKEN_KEYWORD(FINAL_TOK, "final") /* unused */ \ - RS_TOKEN_KEYWORD(FN_TOK, "fn") \ - RS_TOKEN_KEYWORD(FOR, "for") \ - RS_TOKEN_KEYWORD(IF, "if") \ - RS_TOKEN_KEYWORD(IMPL, "impl") \ - RS_TOKEN_KEYWORD(IN, "in") \ - RS_TOKEN_KEYWORD(LET, "let") \ - RS_TOKEN_KEYWORD(LOOP, "loop") \ - RS_TOKEN_KEYWORD(MACRO, "macro") /* unused */ \ - RS_TOKEN_KEYWORD(MATCH_TOK, "match") \ - RS_TOKEN_KEYWORD(MOD, "mod") \ - RS_TOKEN_KEYWORD(MOVE, "move") \ - RS_TOKEN_KEYWORD(MUT, "mut") \ - RS_TOKEN_KEYWORD(OVERRIDE_TOK, "override") /* unused */ \ - RS_TOKEN_KEYWORD(PRIV, "priv") /* unused */ \ - RS_TOKEN_KEYWORD(PUB, "pub") \ - RS_TOKEN_KEYWORD(REF, "ref") \ - RS_TOKEN_KEYWORD(RETURN_TOK, "return") \ - RS_TOKEN_KEYWORD(SELF_ALIAS, "Self") /* mrustc does not treat this as a reserved word*/ \ - RS_TOKEN_KEYWORD(SELF, "self") \ - RS_TOKEN_KEYWORD(STATIC_TOK, "static") \ - RS_TOKEN_KEYWORD(STRUCT_TOK, "struct") \ - RS_TOKEN_KEYWORD(SUPER, "super") \ - RS_TOKEN_KEYWORD(TRAIT, "trait") \ - RS_TOKEN_KEYWORD(TRUE_LITERAL, "true") \ - RS_TOKEN_KEYWORD(TRY, "try") /* unused */ \ - RS_TOKEN_KEYWORD(TYPE, "type") \ - RS_TOKEN_KEYWORD(TYPEOF, "typeof") /* unused */ \ - RS_TOKEN_KEYWORD(UNSAFE, "unsafe") \ - RS_TOKEN_KEYWORD(UNSIZED, "unsized") /* unused */ \ - RS_TOKEN_KEYWORD(USE, "use") \ - RS_TOKEN_KEYWORD(VIRTUAL, "virtual") /* unused */ \ - RS_TOKEN_KEYWORD(WHERE, "where") \ - RS_TOKEN_KEYWORD(WHILE, "while") \ - RS_TOKEN_KEYWORD(YIELD, "yield") /* unused */ \ - \ - RS_TOKEN(LAST_TOKEN, "<last-token-marker>") - - // Contains all token types. Crappy implementation via x-macros. - enum TokenId { +#define RS_TOKEN_LIST \ + RS_TOKEN (FIRST_TOKEN, "<first-token-marker>") \ + RS_TOKEN (END_OF_FILE, "end of file") \ + RS_TOKEN (EXCLAM, "!") \ + RS_TOKEN (NOT_EQUAL, "!=") \ + RS_TOKEN (PERCENT, "%") \ + RS_TOKEN (PERCENT_EQ, "%=") \ + RS_TOKEN (AMP, "&") \ + RS_TOKEN (AMP_EQ, "&=") \ + RS_TOKEN (LOGICAL_AND, "&&") \ + RS_TOKEN (ASTERISK, "*") \ + RS_TOKEN (ASTERISK_EQ, "*=") \ + RS_TOKEN (PLUS, "+") \ + RS_TOKEN (PLUS_EQ, "+=") \ + RS_TOKEN (COMMA, ",") \ + RS_TOKEN (MINUS, "-") \ + RS_TOKEN (MINUS_EQ, "-=") \ + RS_TOKEN (RETURN_TYPE, "->") \ + RS_TOKEN (DOT, ".") \ + RS_TOKEN (DOT_DOT, "..") \ + RS_TOKEN (DOT_DOT_EQ, "..=") \ + RS_TOKEN (ELLIPSIS, "...") \ + RS_TOKEN (DIV, "/") \ + RS_TOKEN (DIV_EQ, "/=") \ + RS_TOKEN (COLON, ":") \ + RS_TOKEN (SEMICOLON, ";") \ + RS_TOKEN (LEFT_SHIFT, "<<") \ + RS_TOKEN (LEFT_SHIFT_EQ, "<<=") \ + RS_TOKEN (LEFT_ANGLE, "<") \ + RS_TOKEN (LESS_OR_EQUAL, "<=") \ + RS_TOKEN (EQUAL, "=") \ + RS_TOKEN (EQUAL_EQUAL, "==") \ + RS_TOKEN (MATCH_ARROW, "=>") \ + RS_TOKEN (RIGHT_ANGLE, ">") \ + RS_TOKEN (GREATER_OR_EQUAL, ">=") \ + RS_TOKEN (RIGHT_SHIFT, ">>") \ + RS_TOKEN (RIGHT_SHIFT_EQ, ">>=") \ + RS_TOKEN (PATTERN_BIND, "@") \ + RS_TOKEN (TILDE, "~") \ + RS_TOKEN (BACKSLASH, "\\") \ + RS_TOKEN (BACKTICK, "`") \ + RS_TOKEN (CARET, "^") \ + RS_TOKEN (CARET_EQ, "^=") \ + RS_TOKEN (PIPE, "|") \ + RS_TOKEN (PIPE_EQ, "|=") \ + RS_TOKEN (OR, "||") \ + RS_TOKEN (QUESTION_MARK, "?") \ + RS_TOKEN (HASH, "#") \ + /* from here on, dodgy and may not be correct. not operators and may be \ + * symbols */ \ + /* RS_TOKEN(SPACE, " ") probably too dodgy */ \ + /* RS_TOKEN(NEWLINE, "\n")*/ \ + RS_TOKEN (SCOPE_RESOLUTION, "::") /* dodgy */ \ + RS_TOKEN (SINGLE_QUOTE, "'") /* should i differentiate from lifetime? */ \ + RS_TOKEN (DOUBLE_QUOTE, "\"") \ + RS_TOKEN (UNDERSCORE, \ + "_") /* TODO: treat as reserved word like mrustc instead? */ \ + RS_TOKEN (IDENTIFIER, "identifier") \ + RS_TOKEN (INT_LITERAL, \ + "integer literal") /* do different int and float types need \ + different literal types? */ \ + RS_TOKEN (FLOAT_LITERAL, "float literal") \ + RS_TOKEN (STRING_LITERAL, "string literal") \ + RS_TOKEN (CHAR_LITERAL, "character literal") \ + RS_TOKEN (BYTE_STRING_LITERAL, "byte string literal") \ + RS_TOKEN (BYTE_CHAR_LITERAL, "byte character literal") \ + RS_TOKEN (LIFETIME, "lifetime") /* TODO: improve token type */ \ + /* Have "interpolated" tokens (whatever that means)? identifer, path, type, \ + * pattern, */ \ + /* expression, statement, block, meta, item in mrustc (but not directly in \ + * lexer). */ \ + RS_TOKEN (LEFT_PAREN, "(") \ + RS_TOKEN (RIGHT_PAREN, ")") \ + RS_TOKEN (LEFT_CURLY, "{") \ + RS_TOKEN (RIGHT_CURLY, "}") \ + RS_TOKEN (LEFT_SQUARE, "[") \ + RS_TOKEN (RIGHT_SQUARE, "]") \ + /* Macros */ \ + RS_TOKEN (DOLLAR_SIGN, "$") \ + /* Comments */ \ + RS_TOKEN (LINE_COMMENT, "//") \ + RS_TOKEN (INNER_LINE_DOC, "//!") \ + RS_TOKEN (OUTER_LINE_DOC, "///") \ + RS_TOKEN (BLOCK_COMMENT_START, "/*") \ + RS_TOKEN (BLOCK_COMMENT_END, "*/") \ + RS_TOKEN (INNER_BLOCK_DOC_START, "/*!") \ + RS_TOKEN (OUTER_BLOCK_DOC_START, \ + "/**") /* have "weak" union and 'static keywords? */ \ + \ + RS_TOKEN_KEYWORD (ABSTRACT, "abstract") /* unused */ \ + RS_TOKEN_KEYWORD (AS, "as") \ + RS_TOKEN_KEYWORD (ASYNC, "async") /* unused */ \ + RS_TOKEN_KEYWORD (BECOME, "become") /* unused */ \ + RS_TOKEN_KEYWORD (BOX, "box") /* unused */ \ + RS_TOKEN_KEYWORD (BREAK, "break") \ + RS_TOKEN_KEYWORD (CONST, "const") \ + RS_TOKEN_KEYWORD (CONTINUE, "continue") \ + RS_TOKEN_KEYWORD (CRATE, "crate") \ + RS_TOKEN_KEYWORD (DO, "do") /* unused */ \ + RS_TOKEN_KEYWORD (DYN, "dyn") \ + RS_TOKEN_KEYWORD (ELSE, "else") \ + RS_TOKEN_KEYWORD (ENUM_TOK, "enum") \ + RS_TOKEN_KEYWORD (EXTERN_TOK, "extern") \ + RS_TOKEN_KEYWORD (FALSE_LITERAL, "false") \ + RS_TOKEN_KEYWORD (FINAL_TOK, "final") /* unused */ \ + RS_TOKEN_KEYWORD (FN_TOK, "fn") \ + RS_TOKEN_KEYWORD (FOR, "for") \ + RS_TOKEN_KEYWORD (IF, "if") \ + RS_TOKEN_KEYWORD (IMPL, "impl") \ + RS_TOKEN_KEYWORD (IN, "in") \ + RS_TOKEN_KEYWORD (LET, "let") \ + RS_TOKEN_KEYWORD (LOOP, "loop") \ + RS_TOKEN_KEYWORD (MACRO, "macro") /* unused */ \ + RS_TOKEN_KEYWORD (MATCH_TOK, "match") \ + RS_TOKEN_KEYWORD (MOD, "mod") \ + RS_TOKEN_KEYWORD (MOVE, "move") \ + RS_TOKEN_KEYWORD (MUT, "mut") \ + RS_TOKEN_KEYWORD (OVERRIDE_TOK, "override") /* unused */ \ + RS_TOKEN_KEYWORD (PRIV, "priv") /* unused */ \ + RS_TOKEN_KEYWORD (PUB, "pub") \ + RS_TOKEN_KEYWORD (REF, "ref") \ + RS_TOKEN_KEYWORD (RETURN_TOK, "return") \ + RS_TOKEN_KEYWORD (SELF_ALIAS, \ + "Self") /* mrustc does not treat this as a reserved word*/ \ + RS_TOKEN_KEYWORD (SELF, "self") \ + RS_TOKEN_KEYWORD (STATIC_TOK, "static") \ + RS_TOKEN_KEYWORD (STRUCT_TOK, "struct") \ + RS_TOKEN_KEYWORD (SUPER, "super") \ + RS_TOKEN_KEYWORD (TRAIT, "trait") \ + RS_TOKEN_KEYWORD (TRUE_LITERAL, "true") \ + RS_TOKEN_KEYWORD (TRY, "try") /* unused */ \ + RS_TOKEN_KEYWORD (TYPE, "type") \ + RS_TOKEN_KEYWORD (TYPEOF, "typeof") /* unused */ \ + RS_TOKEN_KEYWORD (UNSAFE, "unsafe") \ + RS_TOKEN_KEYWORD (UNSIZED, "unsized") /* unused */ \ + RS_TOKEN_KEYWORD (USE, "use") \ + RS_TOKEN_KEYWORD (VIRTUAL, "virtual") /* unused */ \ + RS_TOKEN_KEYWORD (WHERE, "where") \ + RS_TOKEN_KEYWORD (WHILE, "while") \ + RS_TOKEN_KEYWORD (YIELD, "yield") /* unused */ \ + \ + RS_TOKEN (LAST_TOKEN, "<last-token-marker>") + +// Contains all token types. Crappy implementation via x-macros. +enum TokenId +{ #define RS_TOKEN(name, _) name, -#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN(x, y) - RS_TOKEN_LIST +#define RS_TOKEN_KEYWORD(x, y) RS_TOKEN (x, y) + RS_TOKEN_LIST #undef RS_TOKEN_KEYWORD #undef RS_TOKEN - }; - - // dodgy "TokenPtr" declaration with Token forward declaration - class Token; - // A smart pointer (shared_ptr) to Token. - typedef ::std::shared_ptr<Token> TokenPtr; - // A smart pointer (shared_ptr) to a constant Token. - typedef ::std::shared_ptr<const Token> const_TokenPtr; - - // Hackily defined way to get token description for enum value using x-macros - const char* get_token_description(TokenId id); - // Hackily defined way to get token description as a string for enum value using x-macros - const char* token_id_to_str(TokenId id); - // Get type hint description as a string. - const char* get_type_hint_string(PrimitiveCoreType type); - - // Represents a single token. Create using factory static methods. - class Token { - private: - // Token kind. - TokenId token_id; - // Token location. - Location locus; - // Associated text (if any) of token. - ::std::string* str; - // Type hint for token based on lexer data (e.g. type suffix). Does not exist for most tokens. - PrimitiveCoreType type_hint; - - // Token constructor from token id and location. Has a null string. - Token(TokenId token_id, Location location) : - token_id(token_id), locus(location), str(NULL), type_hint(CORETYPE_UNKNOWN) {} - - // Token constructor from token id, location, and a string. - Token(TokenId token_id, Location location, const ::std::string& paramStr) : - token_id(token_id), locus(location), str(new ::std::string(paramStr)), - type_hint(CORETYPE_UNKNOWN) {} - - // Token constructor from token id, location, and a char. - Token(TokenId token_id, Location location, char paramChar) : - token_id(token_id), locus(location), str(new ::std::string(1, paramChar)), - type_hint(CORETYPE_UNKNOWN) {} - - // Token constructor from token id, location, and a "codepoint". - Token(TokenId token_id, Location location, Codepoint paramCodepoint) : - token_id(token_id), locus(location), str(new ::std::string(paramCodepoint.as_string())), - type_hint(CORETYPE_UNKNOWN) {} - - // Token constructor from token id, location, a string, and type hint. - Token(TokenId token_id, Location location, const ::std::string& paramStr, - PrimitiveCoreType parType) : - token_id(token_id), - locus(location), str(new ::std::string(paramStr)), type_hint(parType) {} - - // No default initialiser. - Token(); - // Do not copy/assign tokens. - Token(const Token&); - Token& operator=(const Token&); - - public: - ~Token() { - delete str; - } - - // Makes and returns a new TokenPtr (with null string). - static TokenPtr make(TokenId token_id, Location locus) { - return TokenPtr(new Token(token_id, locus)); - } - - // Makes and returns a new TokenPtr of type IDENTIFIER. - static TokenPtr make_identifier(Location locus, const ::std::string& str) { - return TokenPtr(new Token(IDENTIFIER, locus, str)); - } - - // Makes and returns a new TokenPtr of type INT_LITERAL. - static TokenPtr make_int(Location locus, const ::std::string& str) { - return TokenPtr(new Token(INT_LITERAL, locus, str)); - } - - // Makes and returns a new TokenPtr of type INT_LITERAL. - static TokenPtr make_int( - Location locus, const ::std::string& str, PrimitiveCoreType type_hint) { - return TokenPtr(new Token(INT_LITERAL, locus, str, type_hint)); - } - - // Makes and returns a new TokenPtr of type FLOAT_LITERAL. - static TokenPtr make_float(Location locus, const ::std::string& str) { - return TokenPtr(new Token(FLOAT_LITERAL, locus, str)); - } - - // Makes and returns a new TokenPtr of type FLOAT_LITERAL. - static TokenPtr make_float( - Location locus, const ::std::string& str, PrimitiveCoreType type_hint) { - return TokenPtr(new Token(FLOAT_LITERAL, locus, str, type_hint)); - } - - // Makes and returns a new TokenPtr of type STRING_LITERAL. - static TokenPtr make_string(Location locus, const ::std::string& str) { - return TokenPtr(new Token(STRING_LITERAL, locus, str, CORETYPE_STR)); - } - - // Makes and returns a new TokenPtr of type CHAR_LITERAL (fix). - static TokenPtr make_char(Location locus, Codepoint char_lit) { - return TokenPtr(new Token(CHAR_LITERAL, locus, char_lit)); - } - - // Makes and returns a new TokenPtr of type BYTE_CHAR_LITERAL (fix). - static TokenPtr make_byte_char(Location locus, char byte_char) { - return TokenPtr(new Token(BYTE_CHAR_LITERAL, locus, byte_char)); - } - - // Makes and returns a new TokenPtr of type BYTE_STRING_LITERAL (fix). - static TokenPtr make_byte_string(Location locus, const ::std::string& str) { - return TokenPtr(new Token(BYTE_STRING_LITERAL, locus, str)); - } - - // Makes and returns a new TokenPtr of type LIFETIME. - static TokenPtr make_lifetime(Location locus, const ::std::string& str) { - return TokenPtr(new Token(LIFETIME, locus, str)); - } - - // Gets id of the token. - TokenId get_id() const { - return token_id; - } - - // Gets location of the token. - Location get_locus() const { - return locus; - } - - // Gets string description of the token. - const ::std::string& get_str() const; /*{ - // FIXME: put in header again when fix null problem - //gcc_assert(str != NULL); - if (str == NULL) { - error_at(get_locus(), "attempted to get string for '%s', which has no string. returning empty string instead.", get_token_description()); - return ""; - } - return *str; - }*/ - - // Gets token's type hint info. - PrimitiveCoreType get_type_hint() const { - return type_hint; - } - - // diagnostics (error reporting) - const char* get_token_description() const { - return Rust::get_token_description(token_id); - } - - // debugging - const char* token_id_to_str() const { - return Rust::token_id_to_str(token_id); - } - - // debugging - const char* get_type_hint_str() const; - - /* Returns whether the token is a literal of any type (int, float, char, string, byte char, - * byte string). */ - inline bool is_literal() const { - switch (token_id) { - case INT_LITERAL: - case FLOAT_LITERAL: - case CHAR_LITERAL: - case STRING_LITERAL: - case BYTE_CHAR_LITERAL: - case BYTE_STRING_LITERAL: - return true; - default: - return false; - } - } - - // Returns whether the token actually has a string (regardless of whether it should or not). - inline bool has_str() const { - return str != NULL; - } - - // Returns whether the token should have a string. - inline bool should_have_str() const { - return is_literal() || token_id == IDENTIFIER || token_id == LIFETIME; - } - }; +}; + +// dodgy "TokenPtr" declaration with Token forward declaration +class Token; +// A smart pointer (shared_ptr) to Token. +typedef ::std::shared_ptr<Token> TokenPtr; +// A smart pointer (shared_ptr) to a constant Token. +typedef ::std::shared_ptr<const Token> const_TokenPtr; + +// Hackily defined way to get token description for enum value using x-macros +const char * +get_token_description (TokenId id); +// Hackily defined way to get token description as a string for enum value using +// x-macros +const char * +token_id_to_str (TokenId id); +// Get type hint description as a string. +const char * +get_type_hint_string (PrimitiveCoreType type); + +// Represents a single token. Create using factory static methods. +class Token +{ +private: + // Token kind. + TokenId token_id; + // Token location. + Location locus; + // Associated text (if any) of token. + ::std::string *str; + // Type hint for token based on lexer data (e.g. type suffix). Does not exist + // for most tokens. + PrimitiveCoreType type_hint; + + // Token constructor from token id and location. Has a null string. + Token (TokenId token_id, Location location) + : token_id (token_id), locus (location), str (NULL), + type_hint (CORETYPE_UNKNOWN) + {} + + // Token constructor from token id, location, and a string. + Token (TokenId token_id, Location location, const ::std::string ¶mStr) + : token_id (token_id), locus (location), str (new ::std::string (paramStr)), + type_hint (CORETYPE_UNKNOWN) + {} + + // Token constructor from token id, location, and a char. + Token (TokenId token_id, Location location, char paramChar) + : token_id (token_id), locus (location), + str (new ::std::string (1, paramChar)), type_hint (CORETYPE_UNKNOWN) + {} + + // Token constructor from token id, location, and a "codepoint". + Token (TokenId token_id, Location location, Codepoint paramCodepoint) + : token_id (token_id), locus (location), + str (new ::std::string (paramCodepoint.as_string ())), + type_hint (CORETYPE_UNKNOWN) + {} + + // Token constructor from token id, location, a string, and type hint. + Token (TokenId token_id, Location location, const ::std::string ¶mStr, + PrimitiveCoreType parType) + : token_id (token_id), locus (location), str (new ::std::string (paramStr)), + type_hint (parType) + {} + + // No default initialiser. + Token (); + // Do not copy/assign tokens. + Token (const Token &); + Token &operator= (const Token &); + +public: + ~Token () { delete str; } + + // Makes and returns a new TokenPtr (with null string). + static TokenPtr make (TokenId token_id, Location locus) + { + return TokenPtr (new Token (token_id, locus)); + } + + // Makes and returns a new TokenPtr of type IDENTIFIER. + static TokenPtr make_identifier (Location locus, const ::std::string &str) + { + return TokenPtr (new Token (IDENTIFIER, locus, str)); + } + + // Makes and returns a new TokenPtr of type INT_LITERAL. + static TokenPtr make_int (Location locus, const ::std::string &str) + { + return TokenPtr (new Token (INT_LITERAL, locus, str)); + } + + // Makes and returns a new TokenPtr of type INT_LITERAL. + static TokenPtr make_int (Location locus, const ::std::string &str, + PrimitiveCoreType type_hint) + { + return TokenPtr (new Token (INT_LITERAL, locus, str, type_hint)); + } + + // Makes and returns a new TokenPtr of type FLOAT_LITERAL. + static TokenPtr make_float (Location locus, const ::std::string &str) + { + return TokenPtr (new Token (FLOAT_LITERAL, locus, str)); + } + + // Makes and returns a new TokenPtr of type FLOAT_LITERAL. + static TokenPtr make_float (Location locus, const ::std::string &str, + PrimitiveCoreType type_hint) + { + return TokenPtr (new Token (FLOAT_LITERAL, locus, str, type_hint)); + } + + // Makes and returns a new TokenPtr of type STRING_LITERAL. + static TokenPtr make_string (Location locus, const ::std::string &str) + { + return TokenPtr (new Token (STRING_LITERAL, locus, str, CORETYPE_STR)); + } + + // Makes and returns a new TokenPtr of type CHAR_LITERAL (fix). + static TokenPtr make_char (Location locus, Codepoint char_lit) + { + return TokenPtr (new Token (CHAR_LITERAL, locus, char_lit)); + } + + // Makes and returns a new TokenPtr of type BYTE_CHAR_LITERAL (fix). + static TokenPtr make_byte_char (Location locus, char byte_char) + { + return TokenPtr (new Token (BYTE_CHAR_LITERAL, locus, byte_char)); + } + + // Makes and returns a new TokenPtr of type BYTE_STRING_LITERAL (fix). + static TokenPtr make_byte_string (Location locus, const ::std::string &str) + { + return TokenPtr (new Token (BYTE_STRING_LITERAL, locus, str)); + } + + // Makes and returns a new TokenPtr of type LIFETIME. + static TokenPtr make_lifetime (Location locus, const ::std::string &str) + { + return TokenPtr (new Token (LIFETIME, locus, str)); + } + + // Gets id of the token. + TokenId get_id () const { return token_id; } + + // Gets location of the token. + Location get_locus () const { return locus; } + + // Gets string description of the token. + const ::std::string & + get_str () const; /*{ +// FIXME: put in header again when fix null problem +//gcc_assert(str != NULL); +if (str == NULL) { +error_at(get_locus(), "attempted to get string for '%s', which has no string. +returning empty string instead.", get_token_description()); return ""; } +return *str; +}*/ + + // Gets token's type hint info. + PrimitiveCoreType get_type_hint () const { return type_hint; } + + // diagnostics (error reporting) + const char *get_token_description () const + { + return Rust::get_token_description (token_id); + } + + // debugging + const char *token_id_to_str () const + { + return Rust::token_id_to_str (token_id); + } + + // debugging + const char *get_type_hint_str () const; + + /* Returns whether the token is a literal of any type (int, float, char, + * string, byte char, byte string). */ + inline bool is_literal () const + { + switch (token_id) + { + case INT_LITERAL: + case FLOAT_LITERAL: + case CHAR_LITERAL: + case STRING_LITERAL: + case BYTE_CHAR_LITERAL: + case BYTE_STRING_LITERAL: + return true; + default: + return false; + } + } + + // Returns whether the token actually has a string (regardless of whether it + // should or not). + inline bool has_str () const { return str != NULL; } + + // Returns whether the token should have a string. + inline bool should_have_str () const + { + return is_literal () || token_id == IDENTIFIER || token_id == LIFETIME; + } +}; +} // namespace Rust #endif diff --git a/gcc/rust/operator.h b/gcc/rust/operator.h index 560f4bb..49add60 100644 --- a/gcc/rust/operator.h +++ b/gcc/rust/operator.h @@ -9,60 +9,61 @@ // The operators. -// TODO: Will have to be significantly modified to work with Rust and current setup of gccrs +// TODO: Will have to be significantly modified to work with Rust and current +// setup of gccrs enum Operator { OPERATOR_INVALID, - OPERATOR_OROR, // || - OPERATOR_ANDAND, // && - OPERATOR_EQEQ, // == - OPERATOR_NOTEQ, // != - OPERATOR_LT, // < - OPERATOR_LE, // <= - OPERATOR_GT, // > - OPERATOR_GE, // >= - OPERATOR_PLUS, // + - OPERATOR_MINUS, // - - OPERATOR_OR, // | - OPERATOR_XOR, // ^ - OPERATOR_MULT, // * - OPERATOR_DIV, // / - OPERATOR_MOD, // % - OPERATOR_LSHIFT, // << - OPERATOR_RSHIFT, // >> - OPERATOR_AND, // & - OPERATOR_NOT, // ! - OPERATOR_BITCLEAR, // &^ - OPERATOR_CHANOP, // <- + OPERATOR_OROR, // || + OPERATOR_ANDAND, // && + OPERATOR_EQEQ, // == + OPERATOR_NOTEQ, // != + OPERATOR_LT, // < + OPERATOR_LE, // <= + OPERATOR_GT, // > + OPERATOR_GE, // >= + OPERATOR_PLUS, // + + OPERATOR_MINUS, // - + OPERATOR_OR, // | + OPERATOR_XOR, // ^ + OPERATOR_MULT, // * + OPERATOR_DIV, // / + OPERATOR_MOD, // % + OPERATOR_LSHIFT, // << + OPERATOR_RSHIFT, // >> + OPERATOR_AND, // & + OPERATOR_NOT, // ! + OPERATOR_BITCLEAR, // &^ + OPERATOR_CHANOP, // <- - OPERATOR_EQ, // = - OPERATOR_PLUSEQ, // += - OPERATOR_MINUSEQ, // -= - OPERATOR_OREQ, // |= - OPERATOR_XOREQ, // ^= - OPERATOR_MULTEQ, // *= - OPERATOR_DIVEQ, // /= - OPERATOR_MODEQ, // %= - OPERATOR_LSHIFTEQ, // <<= - OPERATOR_RSHIFTEQ, // >>= - OPERATOR_ANDEQ, // &= - OPERATOR_BITCLEAREQ, // &^= - OPERATOR_PLUSPLUS, // ++ - OPERATOR_MINUSMINUS, // -- + OPERATOR_EQ, // = + OPERATOR_PLUSEQ, // += + OPERATOR_MINUSEQ, // -= + OPERATOR_OREQ, // |= + OPERATOR_XOREQ, // ^= + OPERATOR_MULTEQ, // *= + OPERATOR_DIVEQ, // /= + OPERATOR_MODEQ, // %= + OPERATOR_LSHIFTEQ, // <<= + OPERATOR_RSHIFTEQ, // >>= + OPERATOR_ANDEQ, // &= + OPERATOR_BITCLEAREQ, // &^= + OPERATOR_PLUSPLUS, // ++ + OPERATOR_MINUSMINUS, // -- - OPERATOR_COLON, // : - OPERATOR_COLONEQ, // := - OPERATOR_SEMICOLON, // ; - OPERATOR_DOT, // . - OPERATOR_ELLIPSIS, // ... - OPERATOR_COMMA, // , - OPERATOR_LPAREN, // ( - OPERATOR_RPAREN, // ) - OPERATOR_LCURLY, // { - OPERATOR_RCURLY, // } - OPERATOR_LSQUARE, // [ - OPERATOR_RSQUARE // ] + OPERATOR_COLON, // : + OPERATOR_COLONEQ, // := + OPERATOR_SEMICOLON, // ; + OPERATOR_DOT, // . + OPERATOR_ELLIPSIS, // ... + OPERATOR_COMMA, // , + OPERATOR_LPAREN, // ( + OPERATOR_RPAREN, // ) + OPERATOR_LCURLY, // { + OPERATOR_RCURLY, // } + OPERATOR_LSQUARE, // [ + OPERATOR_RSQUARE // ] }; #endif // !defined(GO_OPERATOR_H) diff --git a/gcc/rust/parse/rust-parse.h b/gcc/rust/parse/rust-parse.h index ca84659..5bc62d3 100644 --- a/gcc/rust/parse/rust-parse.h +++ b/gcc/rust/parse/rust-parse.h @@ -5,455 +5,563 @@ #include "rust-ast-full.h" namespace Rust { - /* HACK: used to resolve the expression-or-statement problem at the end of a block by allowing - * either to be returned (technically). Tagged union would probably take up the same amount of - * space. */ - struct ExprOrStmt { - ::std::unique_ptr<AST::ExprWithoutBlock> expr; - ::std::unique_ptr<AST::Stmt> stmt; - - /* I was going to resist the urge to make this a real class and make it POD, but construction - * in steps is too difficult. So it'll just also have a constructor. */ - - // expression constructor - ExprOrStmt(::std::unique_ptr<AST::ExprWithoutBlock> expr) : expr(::std::move(expr)) {} - - // statement constructor - ExprOrStmt(::std::unique_ptr<AST::Stmt> stmt) : stmt(::std::move(stmt)) {} - - // Returns whether this object is in an error state. - inline bool is_error() const { - return (expr == NULL && stmt == NULL) || (expr != NULL && stmt != NULL); - } - - // Returns an error state object. - static ExprOrStmt create_error() { - return ExprOrStmt(NULL, NULL); - } - - ~ExprOrStmt() = default; - - // no copy constructors/assignment copy as simple object like this shouldn't require it - - // move constructors - ExprOrStmt(ExprOrStmt&& other) = default; - ExprOrStmt& operator=(ExprOrStmt&& other) = default; - - private: - // private constructor only used for creating error state expr or stmt objects - ExprOrStmt(AST::ExprWithoutBlock* expr, AST::Stmt* stmt) : expr(expr), stmt(stmt) {} - - // make this work: have a disambiguation specifically for known statements (i.e. ';' and - // 'let'). then, have a special "parse expr or stmt" function that returns this type. inside - // it, it parses an expression, and then determines whether to return expr or stmt via whether - // the next token is a semicolon. should be able to disambiguate inside that function between - // stmts with blocks and without blocks. - }; - - /* Restrictions on parsing used to signal that certain ambiguous grammar features should be parsed - * in a certain way.*/ - struct ParseRestrictions { - bool can_be_struct_expr = true; - /* Whether the expression was entered from a unary expression - prevents stuff like struct - * exprs being parsed from a dereference. */ - bool entered_from_unary = false; - }; - - // Parser implementation for gccrs. - class Parser { - private: - void skip_after_semicolon(); - void skip_after_end(); - void skip_after_end_block(); - void skip_after_next_block(); - void skip_after_end_attribute(); - - bool skip_token(TokenId t); - const_TokenPtr expect_token(TokenId t); - void unexpected_token(const_TokenPtr t); - bool skip_generics_right_angle(); - - void parse_statement_seq(bool (Parser::*done)()); - - // AST-related stuff - maybe move or something? - ::std::vector<AST::Attribute> parse_inner_attributes(); - AST::Attribute parse_inner_attribute(); - ::std::vector<AST::Attribute> parse_outer_attributes(); - AST::Attribute parse_outer_attribute(); - AST::Attribute parse_attribute_body(); - ::std::unique_ptr<AST::AttrInput> parse_attr_input(); - - // Path-related - AST::SimplePath parse_simple_path(); - AST::SimplePathSegment parse_simple_path_segment(); - AST::TypePath parse_type_path(); - ::std::unique_ptr<AST::TypePathSegment> parse_type_path_segment(); - AST::PathIdentSegment parse_path_ident_segment(); - AST::GenericArgs parse_path_generic_args(); - AST::GenericArgsBinding parse_generic_args_binding(); - AST::TypePathFunction parse_type_path_function(); - AST::PathInExpression parse_path_in_expression(); - AST::PathExprSegment parse_path_expr_segment(); - AST::QualifiedPathInExpression parse_qualified_path_in_expression(bool pratt_parse = false); - AST::QualifiedPathType parse_qualified_path_type(bool pratt_parse = false); - AST::QualifiedPathInType parse_qualified_path_in_type(); - - // Token tree or macro related - AST::DelimTokenTree parse_delim_token_tree(); - ::std::unique_ptr<AST::TokenTree> parse_token_tree(); - ::std::unique_ptr<AST::MacroRulesDefinition> parse_macro_rules_def( - ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::MacroInvocationSemi> parse_macro_invocation_semi( - ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::MacroInvocation> parse_macro_invocation( - ::std::vector<AST::Attribute> outer_attrs); - AST::MacroRule parse_macro_rule(); - AST::MacroMatcher parse_macro_matcher(); - ::std::unique_ptr<AST::MacroMatch> parse_macro_match(); - ::std::unique_ptr<AST::MacroMatchFragment> parse_macro_match_fragment(); - ::std::unique_ptr<AST::MacroMatchRepetition> parse_macro_match_repetition(); - - // Top-level item-related - ::std::vector< ::std::unique_ptr<AST::Item> > parse_items(); - ::std::unique_ptr<AST::Item> parse_item(bool called_from_statement); - ::std::unique_ptr<AST::VisItem> parse_vis_item(::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::MacroItem> parse_macro_item(::std::vector<AST::Attribute> outer_attrs); - AST::Visibility parse_visibility(); - - // VisItem subclass-related - ::std::unique_ptr<AST::Module> parse_module( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::ExternCrate> parse_extern_crate( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::UseDeclaration> parse_use_decl( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::UseTree> parse_use_tree(); - ::std::unique_ptr<AST::Function> parse_function( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - AST::FunctionQualifiers parse_function_qualifiers(); - ::std::vector< ::std::unique_ptr<AST::GenericParam> > parse_generic_params_in_angles(); - ::std::vector< ::std::unique_ptr<AST::GenericParam> > parse_generic_params(); - ::std::vector< ::std::unique_ptr<AST::LifetimeParam> > parse_lifetime_params(); - ::std::vector<AST::LifetimeParam> parse_lifetime_params_objs(); - AST::LifetimeParam parse_lifetime_param(); - ::std::vector< ::std::unique_ptr<AST::TypeParam> > parse_type_params(); - ::std::unique_ptr<AST::TypeParam> parse_type_param(); - ::std::vector<AST::FunctionParam> parse_function_params(); - AST::FunctionParam parse_function_param(); - ::std::unique_ptr<AST::Type> parse_function_return_type(); - AST::WhereClause parse_where_clause(); - ::std::unique_ptr<AST::WhereClauseItem> parse_where_clause_item(); - ::std::unique_ptr<AST::LifetimeWhereClauseItem> parse_lifetime_where_clause_item(); - ::std::unique_ptr<AST::TypeBoundWhereClauseItem> parse_type_bound_where_clause_item(); - ::std::vector<AST::LifetimeParam> parse_for_lifetimes(); - ::std::vector< ::std::unique_ptr<AST::TypeParamBound> > parse_type_param_bounds(); - ::std::unique_ptr<AST::TypeParamBound> parse_type_param_bound(); - ::std::unique_ptr<AST::TraitBound> parse_trait_bound(); - ::std::vector<AST::Lifetime> parse_lifetime_bounds(); - AST::Lifetime parse_lifetime(); - ::std::unique_ptr<AST::TypeAlias> parse_type_alias( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::Struct> parse_struct( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::vector<AST::StructField> parse_struct_fields(); - AST::StructField parse_struct_field(); - ::std::vector<AST::TupleField> parse_tuple_fields(); - AST::TupleField parse_tuple_field(); - ::std::unique_ptr<AST::Enum> parse_enum( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::vector< ::std::unique_ptr<AST::EnumItem> > parse_enum_items(); - ::std::unique_ptr<AST::EnumItem> parse_enum_item(); - ::std::unique_ptr<AST::Union> parse_union( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::ConstantItem> parse_const_item( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::StaticItem> parse_static_item( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::Trait> parse_trait( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::TraitItem> parse_trait_item(); - ::std::unique_ptr<AST::TraitItemType> parse_trait_type( - ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::TraitItemConst> parse_trait_const( - ::std::vector<AST::Attribute> outer_attrs); - AST::SelfParam parse_self_param(); - ::std::unique_ptr<AST::Impl> parse_impl( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item(); - ::std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_function_or_method( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item(); - ::std::unique_ptr<AST::TraitImplItem> parse_trait_impl_function_or_method( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::ExternBlock> parse_extern_block( - AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::ExternalItem> parse_external_item(); - AST::NamedFunctionParam parse_named_function_param(); - AST::Method parse_method(); - - // Expression-related (Pratt parsed) - ::std::unique_ptr<AST::Expr> parse_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::Expr> parse_expr(int right_binding_power, - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::Expr> null_denotation_NEW(const_TokenPtr t, - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::Expr> left_denotation(const_TokenPtr t, - ::std::unique_ptr<AST::Expr> left, - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_binary_plus_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_binary_minus_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_binary_mult_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_binary_div_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_binary_mod_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_bitwise_and_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_bitwise_or_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_bitwise_xor_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_left_shift_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_right_shift_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ComparisonExpr> parse_binary_equal_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ComparisonExpr> parse_binary_not_equal_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ComparisonExpr> parse_binary_greater_than_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ComparisonExpr> parse_binary_less_than_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ComparisonExpr> parse_binary_greater_equal_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ComparisonExpr> parse_binary_less_equal_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::LazyBooleanExpr> parse_lazy_or_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::LazyBooleanExpr> parse_lazy_and_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::TypeCastExpr> parse_type_cast_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> expr_to_cast, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::AssignmentExpr> parse_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_plus_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_minus_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_mult_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_div_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_mod_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_and_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_or_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_xor_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_left_shift_assig_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_right_shift_assig_expr( - const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, - ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::AwaitExpr> parse_await_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> expr_to_await, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::MethodCallExpr> parse_method_call_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> receiver_expr, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::CallExpr> parse_function_call_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> function_expr, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::RangeExpr> parse_led_range_exclusive_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::RangeExpr> parse_nud_range_exclusive_expr( - const_TokenPtr tok, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::RangeFromToInclExpr> parse_range_inclusive_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> left, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::RangeToInclExpr> parse_range_to_inclusive_expr( - const_TokenPtr tok, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::TupleIndexExpr> parse_tuple_index_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> tuple_expr, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::FieldAccessExpr> parse_field_access_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> struct_expr, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::ArrayIndexExpr> parse_index_expr(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> array_expr, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - ::std::unique_ptr<AST::MacroInvocation> parse_macro_invocation_partial( - AST::PathInExpression path, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::StructExprStruct> parse_struct_expr_struct_partial( - AST::PathInExpression path, ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::StructExprTuple> parse_struct_expr_tuple_partial( - AST::PathInExpression path, ::std::vector<AST::Attribute> outer_attrs); - AST::PathInExpression parse_path_in_expression_pratt(const_TokenPtr tok); - ::std::unique_ptr<AST::ClosureExpr> parse_closure_expr_pratt(const_TokenPtr tok, - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - ::std::unique_ptr<AST::TupleIndexExpr> parse_tuple_index_expr_float(const_TokenPtr tok, - ::std::unique_ptr<AST::Expr> tuple_expr, ::std::vector<AST::Attribute> outer_attrs, - ParseRestrictions restrictions = ParseRestrictions()); - - // Expression-related (non-Pratt parsed) - ::std::unique_ptr<AST::ExprWithoutBlock> parse_expr_without_block( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - ::std::unique_ptr<AST::BlockExpr> parse_block_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - bool pratt_parse = false); - ::std::unique_ptr<AST::IfExpr> parse_if_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - ::std::unique_ptr<AST::IfLetExpr> parse_if_let_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - ::std::unique_ptr<AST::LoopExpr> parse_loop_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - AST::LoopLabel label = AST::LoopLabel::error()); - ::std::unique_ptr<AST::WhileLoopExpr> parse_while_loop_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - AST::LoopLabel label = AST::LoopLabel::error()); - ::std::unique_ptr<AST::WhileLetLoopExpr> parse_while_let_loop_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - AST::LoopLabel label = AST::LoopLabel::error()); - ::std::unique_ptr<AST::ForLoopExpr> parse_for_loop_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - AST::LoopLabel label = AST::LoopLabel::error()); - ::std::unique_ptr<AST::MatchExpr> parse_match_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - bool pratt_parse = false); - AST::MatchArm parse_match_arm(); - ::std::vector< ::std::unique_ptr<AST::Pattern> > parse_match_arm_patterns( - TokenId end_token_id); - ::std::unique_ptr<AST::BaseLoopExpr> parse_labelled_loop_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - AST::LoopLabel parse_loop_label(); - ::std::unique_ptr<AST::AsyncBlockExpr> parse_async_block_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - ::std::unique_ptr<AST::UnsafeBlockExpr> parse_unsafe_block_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - ::std::unique_ptr<AST::GroupedExpr> parse_grouped_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - ::std::unique_ptr<AST::ClosureExpr> parse_closure_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - AST::ClosureParam parse_closure_param(); - ::std::unique_ptr<AST::LiteralExpr> parse_literal_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>()); - ::std::unique_ptr<AST::ReturnExpr> parse_return_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - bool pratt_parse = false); - ::std::unique_ptr<AST::BreakExpr> parse_break_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - bool pratt_parse = false); - ::std::unique_ptr<AST::ContinueExpr> parse_continue_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - bool pratt_parse = false); - ::std::unique_ptr<AST::ArrayExpr> parse_array_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - bool pratt_parse = false); - ::std::unique_ptr<AST::ExprWithoutBlock> parse_grouped_or_tuple_expr( - ::std::vector<AST::Attribute> outer_attrs = ::std::vector<AST::Attribute>(), - bool pratt_parse = false); - ::std::unique_ptr<AST::StructExprField> parse_struct_expr_field(); - - // Type-related - ::std::unique_ptr<AST::Type> parse_type(); - ::std::unique_ptr<AST::TypeNoBounds> parse_type_no_bounds(); - ::std::unique_ptr<AST::TypeNoBounds> parse_slice_or_array_type(); - ::std::unique_ptr<AST::RawPointerType> parse_raw_pointer_type(); - ::std::unique_ptr<AST::ReferenceType> parse_reference_type(); - ::std::unique_ptr<AST::BareFunctionType> parse_bare_function_type( - ::std::vector<AST::LifetimeParam> for_lifetimes); - ::std::unique_ptr<AST::Type> parse_paren_prefixed_type(); - ::std::unique_ptr<AST::TypeNoBounds> parse_paren_prefixed_type_no_bounds(); - ::std::unique_ptr<AST::Type> parse_for_prefixed_type(); - AST::MaybeNamedParam parse_maybe_named_param(); - - // Statement-related - ::std::unique_ptr<AST::Stmt> parse_stmt(); - ::std::unique_ptr<AST::LetStmt> parse_let_stmt(::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::ExprStmt> parse_expr_stmt(::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::ExprStmtWithBlock> parse_expr_stmt_with_block( - ::std::vector<AST::Attribute> outer_attrs); - ::std::unique_ptr<AST::ExprStmtWithoutBlock> parse_expr_stmt_without_block( - ::std::vector<AST::Attribute> outer_attrs); - ExprOrStmt parse_stmt_or_expr_without_block(); - ExprOrStmt parse_macro_invocation_maybe_semi(::std::vector<AST::Attribute> outer_attrs); - ExprOrStmt parse_path_based_stmt_or_expr(::std::vector<AST::Attribute> outer_attrs); - - // Pattern-related - ::std::unique_ptr<AST::Pattern> parse_pattern(); - ::std::unique_ptr<AST::Pattern> parse_literal_or_range_pattern(); - ::std::unique_ptr<AST::RangePatternBound> parse_range_pattern_bound(); - ::std::unique_ptr<AST::ReferencePattern> parse_reference_pattern(); - ::std::unique_ptr<AST::Pattern> parse_grouped_or_tuple_pattern(); - ::std::unique_ptr<AST::SlicePattern> parse_slice_pattern(); - ::std::unique_ptr<AST::IdentifierPattern> parse_identifier_pattern(); - ::std::unique_ptr<AST::Pattern> parse_ident_leading_pattern(); - ::std::unique_ptr<AST::TupleStructItems> parse_tuple_struct_items(); - AST::StructPatternElements parse_struct_pattern_elems(); - ::std::unique_ptr<AST::StructPatternField> parse_struct_pattern_field(); - - int left_binding_power(const_TokenPtr token); - - bool done_end(); - bool done_end_or_else(); - bool done_end_of_file(); - - public: - // Construct parser with specified lexer reference. - Parser(Lexer& parLexer) : lexer(parLexer) {} - - // Main entry point for parser. - AST::Crate parse_crate(); - - // Dumps all lexer output. - void debug_dump_lex_output(); - void debug_dump_ast_output(); - - private: - // The lexer associated with the parser. - Lexer& lexer; - }; -} +/* HACK: used to resolve the expression-or-statement problem at the end of a + * block by allowing either to be returned (technically). Tagged union would + * probably take up the same amount of space. */ +struct ExprOrStmt +{ + ::std::unique_ptr<AST::ExprWithoutBlock> expr; + ::std::unique_ptr<AST::Stmt> stmt; + + /* I was going to resist the urge to make this a real class and make it POD, + * but construction in steps is too difficult. So it'll just also have a + * constructor. */ + + // expression constructor + ExprOrStmt (::std::unique_ptr<AST::ExprWithoutBlock> expr) + : expr (::std::move (expr)) + {} + + // statement constructor + ExprOrStmt (::std::unique_ptr<AST::Stmt> stmt) : stmt (::std::move (stmt)) {} + + // Returns whether this object is in an error state. + inline bool is_error () const + { + return (expr == NULL && stmt == NULL) || (expr != NULL && stmt != NULL); + } + + // Returns an error state object. + static ExprOrStmt create_error () { return ExprOrStmt (NULL, NULL); } + + ~ExprOrStmt () = default; + + // no copy constructors/assignment copy as simple object like this shouldn't + // require it + + // move constructors + ExprOrStmt (ExprOrStmt &&other) = default; + ExprOrStmt &operator= (ExprOrStmt &&other) = default; + +private: + // private constructor only used for creating error state expr or stmt objects + ExprOrStmt (AST::ExprWithoutBlock *expr, AST::Stmt *stmt) + : expr (expr), stmt (stmt) + {} + + // make this work: have a disambiguation specifically for known statements + // (i.e. ';' and 'let'). then, have a special "parse expr or stmt" function + // that returns this type. inside it, it parses an expression, and then + // determines whether to return expr or stmt via whether the next token is a + // semicolon. should be able to disambiguate inside that function between + // stmts with blocks and without blocks. +}; + +/* Restrictions on parsing used to signal that certain ambiguous grammar + * features should be parsed in a certain way.*/ +struct ParseRestrictions +{ + bool can_be_struct_expr = true; + /* Whether the expression was entered from a unary expression - prevents stuff + * like struct exprs being parsed from a dereference. */ + bool entered_from_unary = false; +}; + +// Parser implementation for gccrs. +class Parser +{ +private: + void skip_after_semicolon (); + void skip_after_end (); + void skip_after_end_block (); + void skip_after_next_block (); + void skip_after_end_attribute (); + + bool skip_token (TokenId t); + const_TokenPtr expect_token (TokenId t); + void unexpected_token (const_TokenPtr t); + bool skip_generics_right_angle (); + + void parse_statement_seq (bool (Parser::*done) ()); + + // AST-related stuff - maybe move or something? + ::std::vector<AST::Attribute> parse_inner_attributes (); + AST::Attribute parse_inner_attribute (); + ::std::vector<AST::Attribute> parse_outer_attributes (); + AST::Attribute parse_outer_attribute (); + AST::Attribute parse_attribute_body (); + ::std::unique_ptr<AST::AttrInput> parse_attr_input (); + + // Path-related + AST::SimplePath parse_simple_path (); + AST::SimplePathSegment parse_simple_path_segment (); + AST::TypePath parse_type_path (); + ::std::unique_ptr<AST::TypePathSegment> parse_type_path_segment (); + AST::PathIdentSegment parse_path_ident_segment (); + AST::GenericArgs parse_path_generic_args (); + AST::GenericArgsBinding parse_generic_args_binding (); + AST::TypePathFunction parse_type_path_function (); + AST::PathInExpression parse_path_in_expression (); + AST::PathExprSegment parse_path_expr_segment (); + AST::QualifiedPathInExpression + parse_qualified_path_in_expression (bool pratt_parse = false); + AST::QualifiedPathType parse_qualified_path_type (bool pratt_parse = false); + AST::QualifiedPathInType parse_qualified_path_in_type (); + + // Token tree or macro related + AST::DelimTokenTree parse_delim_token_tree (); + ::std::unique_ptr<AST::TokenTree> parse_token_tree (); + ::std::unique_ptr<AST::MacroRulesDefinition> + parse_macro_rules_def (::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::MacroInvocationSemi> + parse_macro_invocation_semi (::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::MacroInvocation> + parse_macro_invocation (::std::vector<AST::Attribute> outer_attrs); + AST::MacroRule parse_macro_rule (); + AST::MacroMatcher parse_macro_matcher (); + ::std::unique_ptr<AST::MacroMatch> parse_macro_match (); + ::std::unique_ptr<AST::MacroMatchFragment> parse_macro_match_fragment (); + ::std::unique_ptr<AST::MacroMatchRepetition> parse_macro_match_repetition (); + + // Top-level item-related + ::std::vector< ::std::unique_ptr<AST::Item> > parse_items (); + ::std::unique_ptr<AST::Item> parse_item (bool called_from_statement); + ::std::unique_ptr<AST::VisItem> + parse_vis_item (::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::MacroItem> + parse_macro_item (::std::vector<AST::Attribute> outer_attrs); + AST::Visibility parse_visibility (); + + // VisItem subclass-related + ::std::unique_ptr<AST::Module> + parse_module (AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::ExternCrate> + parse_extern_crate (AST::Visibility vis, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::UseDeclaration> + parse_use_decl (AST::Visibility vis, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::UseTree> parse_use_tree (); + ::std::unique_ptr<AST::Function> + parse_function (AST::Visibility vis, + ::std::vector<AST::Attribute> outer_attrs); + AST::FunctionQualifiers parse_function_qualifiers (); + ::std::vector< ::std::unique_ptr<AST::GenericParam> > + parse_generic_params_in_angles (); + ::std::vector< ::std::unique_ptr<AST::GenericParam> > parse_generic_params (); + ::std::vector< ::std::unique_ptr<AST::LifetimeParam> > + parse_lifetime_params (); + ::std::vector<AST::LifetimeParam> parse_lifetime_params_objs (); + AST::LifetimeParam parse_lifetime_param (); + ::std::vector< ::std::unique_ptr<AST::TypeParam> > parse_type_params (); + ::std::unique_ptr<AST::TypeParam> parse_type_param (); + ::std::vector<AST::FunctionParam> parse_function_params (); + AST::FunctionParam parse_function_param (); + ::std::unique_ptr<AST::Type> parse_function_return_type (); + AST::WhereClause parse_where_clause (); + ::std::unique_ptr<AST::WhereClauseItem> parse_where_clause_item (); + ::std::unique_ptr<AST::LifetimeWhereClauseItem> + parse_lifetime_where_clause_item (); + ::std::unique_ptr<AST::TypeBoundWhereClauseItem> + parse_type_bound_where_clause_item (); + ::std::vector<AST::LifetimeParam> parse_for_lifetimes (); + ::std::vector< ::std::unique_ptr<AST::TypeParamBound> > + parse_type_param_bounds (); + ::std::unique_ptr<AST::TypeParamBound> parse_type_param_bound (); + ::std::unique_ptr<AST::TraitBound> parse_trait_bound (); + ::std::vector<AST::Lifetime> parse_lifetime_bounds (); + AST::Lifetime parse_lifetime (); + ::std::unique_ptr<AST::TypeAlias> + parse_type_alias (AST::Visibility vis, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::Struct> + parse_struct (AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); + ::std::vector<AST::StructField> parse_struct_fields (); + AST::StructField parse_struct_field (); + ::std::vector<AST::TupleField> parse_tuple_fields (); + AST::TupleField parse_tuple_field (); + ::std::unique_ptr<AST::Enum> + parse_enum (AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); + ::std::vector< ::std::unique_ptr<AST::EnumItem> > parse_enum_items (); + ::std::unique_ptr<AST::EnumItem> parse_enum_item (); + ::std::unique_ptr<AST::Union> + parse_union (AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::ConstantItem> + parse_const_item (AST::Visibility vis, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::StaticItem> + parse_static_item (AST::Visibility vis, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::Trait> + parse_trait (AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::TraitItem> parse_trait_item (); + ::std::unique_ptr<AST::TraitItemType> + parse_trait_type (::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::TraitItemConst> + parse_trait_const (::std::vector<AST::Attribute> outer_attrs); + AST::SelfParam parse_self_param (); + ::std::unique_ptr<AST::Impl> + parse_impl (AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::InherentImplItem> parse_inherent_impl_item (); + ::std::unique_ptr<AST::InherentImplItem> + parse_inherent_impl_function_or_method ( + AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::TraitImplItem> parse_trait_impl_item (); + ::std::unique_ptr<AST::TraitImplItem> parse_trait_impl_function_or_method ( + AST::Visibility vis, ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::ExternBlock> + parse_extern_block (AST::Visibility vis, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::ExternalItem> parse_external_item (); + AST::NamedFunctionParam parse_named_function_param (); + AST::Method parse_method (); + + // Expression-related (Pratt parsed) + ::std::unique_ptr<AST::Expr> + parse_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::Expr> + parse_expr (int right_binding_power, + ::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::Expr> + null_denotation_NEW (const_TokenPtr t, + ::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::Expr> + left_denotation (const_TokenPtr t, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> + parse_binary_plus_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> parse_binary_minus_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> + parse_binary_mult_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> + parse_binary_div_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> + parse_binary_mod_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> + parse_bitwise_and_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> + parse_bitwise_or_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> + parse_bitwise_xor_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> + parse_left_shift_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ArithmeticOrLogicalExpr> + parse_right_shift_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + ::std::unique_ptr<AST::ComparisonExpr> parse_binary_equal_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ComparisonExpr> parse_binary_not_equal_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ComparisonExpr> parse_binary_greater_than_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ComparisonExpr> parse_binary_less_than_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ComparisonExpr> parse_binary_greater_equal_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ComparisonExpr> parse_binary_less_equal_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::LazyBooleanExpr> + parse_lazy_or_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::LazyBooleanExpr> + parse_lazy_and_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::TypeCastExpr> + parse_type_cast_expr (const_TokenPtr tok, + ::std::unique_ptr<AST::Expr> expr_to_cast, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::AssignmentExpr> + parse_assig_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> + parse_plus_assig_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> + parse_minus_assig_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions + = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> + parse_mult_assig_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> + parse_div_assig_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> + parse_mod_assig_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> + parse_and_assig_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> + parse_or_assig_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> + parse_xor_assig_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_left_shift_assig_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CompoundAssignmentExpr> parse_right_shift_assig_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::AwaitExpr> + parse_await_expr (const_TokenPtr tok, + ::std::unique_ptr<AST::Expr> expr_to_await, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::MethodCallExpr> parse_method_call_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> receiver_expr, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::CallExpr> parse_function_call_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> function_expr, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::RangeExpr> parse_led_range_exclusive_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::RangeExpr> + parse_nud_range_exclusive_expr (const_TokenPtr tok, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::RangeFromToInclExpr> parse_range_inclusive_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> left, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::RangeToInclExpr> + parse_range_to_inclusive_expr (const_TokenPtr tok, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::TupleIndexExpr> parse_tuple_index_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> tuple_expr, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::FieldAccessExpr> parse_field_access_expr ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> struct_expr, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::ArrayIndexExpr> + parse_index_expr (const_TokenPtr tok, ::std::unique_ptr<AST::Expr> array_expr, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + ::std::unique_ptr<AST::MacroInvocation> + parse_macro_invocation_partial (AST::PathInExpression path, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::StructExprStruct> + parse_struct_expr_struct_partial (AST::PathInExpression path, + ::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::StructExprTuple> + parse_struct_expr_tuple_partial (AST::PathInExpression path, + ::std::vector<AST::Attribute> outer_attrs); + AST::PathInExpression parse_path_in_expression_pratt (const_TokenPtr tok); + ::std::unique_ptr<AST::ClosureExpr> + parse_closure_expr_pratt (const_TokenPtr tok, + ::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + ::std::unique_ptr<AST::TupleIndexExpr> parse_tuple_index_expr_float ( + const_TokenPtr tok, ::std::unique_ptr<AST::Expr> tuple_expr, + ::std::vector<AST::Attribute> outer_attrs, + ParseRestrictions restrictions = ParseRestrictions ()); + + // Expression-related (non-Pratt parsed) + ::std::unique_ptr<AST::ExprWithoutBlock> + parse_expr_without_block (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + ::std::unique_ptr<AST::BlockExpr> + parse_block_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + bool pratt_parse = false); + ::std::unique_ptr<AST::IfExpr> + parse_if_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + ::std::unique_ptr<AST::IfLetExpr> + parse_if_let_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + ::std::unique_ptr<AST::LoopExpr> + parse_loop_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + AST::LoopLabel label = AST::LoopLabel::error ()); + ::std::unique_ptr<AST::WhileLoopExpr> + parse_while_loop_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + AST::LoopLabel label = AST::LoopLabel::error ()); + ::std::unique_ptr<AST::WhileLetLoopExpr> + parse_while_let_loop_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + AST::LoopLabel label = AST::LoopLabel::error ()); + ::std::unique_ptr<AST::ForLoopExpr> + parse_for_loop_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + AST::LoopLabel label = AST::LoopLabel::error ()); + ::std::unique_ptr<AST::MatchExpr> + parse_match_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + bool pratt_parse = false); + AST::MatchArm parse_match_arm (); + ::std::vector< ::std::unique_ptr<AST::Pattern> > + parse_match_arm_patterns (TokenId end_token_id); + ::std::unique_ptr<AST::BaseLoopExpr> + parse_labelled_loop_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + AST::LoopLabel parse_loop_label (); + ::std::unique_ptr<AST::AsyncBlockExpr> + parse_async_block_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + ::std::unique_ptr<AST::UnsafeBlockExpr> + parse_unsafe_block_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + ::std::unique_ptr<AST::GroupedExpr> + parse_grouped_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + ::std::unique_ptr<AST::ClosureExpr> + parse_closure_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + AST::ClosureParam parse_closure_param (); + ::std::unique_ptr<AST::LiteralExpr> + parse_literal_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> ()); + ::std::unique_ptr<AST::ReturnExpr> + parse_return_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + bool pratt_parse = false); + ::std::unique_ptr<AST::BreakExpr> + parse_break_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + bool pratt_parse = false); + ::std::unique_ptr<AST::ContinueExpr> + parse_continue_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + bool pratt_parse = false); + ::std::unique_ptr<AST::ArrayExpr> + parse_array_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + bool pratt_parse = false); + ::std::unique_ptr<AST::ExprWithoutBlock> + parse_grouped_or_tuple_expr (::std::vector<AST::Attribute> outer_attrs + = ::std::vector<AST::Attribute> (), + bool pratt_parse = false); + ::std::unique_ptr<AST::StructExprField> parse_struct_expr_field (); + + // Type-related + ::std::unique_ptr<AST::Type> parse_type (); + ::std::unique_ptr<AST::TypeNoBounds> parse_type_no_bounds (); + ::std::unique_ptr<AST::TypeNoBounds> parse_slice_or_array_type (); + ::std::unique_ptr<AST::RawPointerType> parse_raw_pointer_type (); + ::std::unique_ptr<AST::ReferenceType> parse_reference_type (); + ::std::unique_ptr<AST::BareFunctionType> + parse_bare_function_type (::std::vector<AST::LifetimeParam> for_lifetimes); + ::std::unique_ptr<AST::Type> parse_paren_prefixed_type (); + ::std::unique_ptr<AST::TypeNoBounds> parse_paren_prefixed_type_no_bounds (); + ::std::unique_ptr<AST::Type> parse_for_prefixed_type (); + AST::MaybeNamedParam parse_maybe_named_param (); + + // Statement-related + ::std::unique_ptr<AST::Stmt> parse_stmt (); + ::std::unique_ptr<AST::LetStmt> + parse_let_stmt (::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::ExprStmt> + parse_expr_stmt (::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::ExprStmtWithBlock> + parse_expr_stmt_with_block (::std::vector<AST::Attribute> outer_attrs); + ::std::unique_ptr<AST::ExprStmtWithoutBlock> + parse_expr_stmt_without_block (::std::vector<AST::Attribute> outer_attrs); + ExprOrStmt parse_stmt_or_expr_without_block (); + ExprOrStmt + parse_macro_invocation_maybe_semi (::std::vector<AST::Attribute> outer_attrs); + ExprOrStmt + parse_path_based_stmt_or_expr (::std::vector<AST::Attribute> outer_attrs); + + // Pattern-related + ::std::unique_ptr<AST::Pattern> parse_pattern (); + ::std::unique_ptr<AST::Pattern> parse_literal_or_range_pattern (); + ::std::unique_ptr<AST::RangePatternBound> parse_range_pattern_bound (); + ::std::unique_ptr<AST::ReferencePattern> parse_reference_pattern (); + ::std::unique_ptr<AST::Pattern> parse_grouped_or_tuple_pattern (); + ::std::unique_ptr<AST::SlicePattern> parse_slice_pattern (); + ::std::unique_ptr<AST::IdentifierPattern> parse_identifier_pattern (); + ::std::unique_ptr<AST::Pattern> parse_ident_leading_pattern (); + ::std::unique_ptr<AST::TupleStructItems> parse_tuple_struct_items (); + AST::StructPatternElements parse_struct_pattern_elems (); + ::std::unique_ptr<AST::StructPatternField> parse_struct_pattern_field (); + + int left_binding_power (const_TokenPtr token); + + bool done_end (); + bool done_end_or_else (); + bool done_end_of_file (); + +public: + // Construct parser with specified lexer reference. + Parser (Lexer &parLexer) : lexer (parLexer) {} + + // Main entry point for parser. + AST::Crate parse_crate (); + + // Dumps all lexer output. + void debug_dump_lex_output (); + void debug_dump_ast_output (); + +private: + // The lexer associated with the parser. + Lexer &lexer; +}; +} // namespace Rust #endif // RUST_PARSE_H diff --git a/gcc/rust/rust-backend.c b/gcc/rust/rust-backend.c index fb701ce..49c7ebd 100644 --- a/gcc/rust/rust-backend.c +++ b/gcc/rust/rust-backend.c @@ -1,21 +1,21 @@ /* rust-backend.c -- Rust frontend interface to gcc backend. - Copyright (C) 2010-2019 Free Software Foundation, Inc. + Copyright (C) 2010-2020 Free Software Foundation, Inc. -This file is part of GCC. + 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 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. + 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/>. */ + 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 "config.h" #include "system.h" @@ -28,7 +28,7 @@ along with GCC; see the file COPYING3. If not see #include "simple-object.h" #include "stor-layout.h" #include "intl.h" -#include "output.h" /* for assemble_string */ +#include "output.h" /* for assemble_string */ #include "common/common-target.h" //#include "rust-c.h" // import no longer exists, so hopefully not broken @@ -110,8 +110,8 @@ rust_write_export_data (const char *bytes, unsigned int size) { gcc_assert (targetm_common.have_named_sections); sec = get_section (RUST_EXPORT_SECTION_NAME, - TARGET_AIX ? SECTION_EXCLUDE : SECTION_DEBUG, - NULL); + TARGET_AIX ? SECTION_EXCLUDE : SECTION_DEBUG, + NULL); } switch_to_section (sec); @@ -131,7 +131,7 @@ rust_write_export_data (const char *bytes, unsigned int size) const char * rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, - int *perr) + int *perr) { simple_object_read *sobj; const char *errmsg; @@ -145,20 +145,20 @@ rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, *plen = 0; sobj = simple_object_start_read (fd, offset, RUST_EXPORT_SEGMENT_NAME, - &errmsg, perr); + &errmsg, perr); if (sobj == NULL) { /* If we get an error here, just pretend that we didn't find any - export data. This is the right thing to do if the error is - that the file was not recognized as an object file. This - will ignore file I/O errors, but it's not too big a deal - because we will wind up giving some other error later. */ + export data. This is the right thing to do if the error is + that the file was not recognized as an object file. This + will ignore file I/O errors, but it's not too big a deal + because we will wind up giving some other error later. */ return NULL; } found = simple_object_find_section (sobj, RUST_EXPORT_SECTION_NAME, - &sec_offset, &sec_length, - &errmsg, perr); + &sec_offset, &sec_length, + &errmsg, perr); simple_object_release_read (sobj); if (!found) return errmsg; diff --git a/gcc/rust/rust-buffered-queue.h b/gcc/rust/rust-buffered-queue.h index ac0ea1a..f56aaff 100644 --- a/gcc/rust/rust-buffered-queue.h +++ b/gcc/rust/rust-buffered-queue.h @@ -8,123 +8,138 @@ // order: config, system namespace Rust { - // Buffered queue implementation. Items are of type T, queue source is of type Source. - template<typename T, typename Source> - class buffered_queue { - public: - // Construct empty queue from Source& src. - buffered_queue(Source& src) : source(src), start(0), end(0), buffer() {} - - // Returns token at position start + n (i.e. n tokens ahead). - T peek(int n) { - // n should not be behind - gcc_assert(n >= 0); - - int num_queued_items = end - start; - int num_items_required = n + 1; - - // if required items go past end of queue, add them to queue - if (num_items_required > num_queued_items) { - int num_items_to_read = num_items_required - num_queued_items; - - // if queue length + extra items is larger than buffer size, expand buffer - if (end + num_items_to_read > (int)buffer.size()) { - // Resize the buffer by 1.5x - int new_size = (buffer.size() + num_items_to_read); - new_size += (new_size >> 1); - - // create new queue buffer with new size - std::vector<T> new_queue(new_size); - std::copy(buffer.begin() + start, buffer.begin() + end, new_queue.begin()); - start = 0; - end = num_queued_items; - - // swap member buffer and new queue buffer - std::swap(buffer, new_queue); - - // validate that buffer is large enough now - gcc_assert(end + num_queued_items < (int)buffer.size()); - } - - // iterate through buffer and invoke operator () on source on values past original end - for (int i = 0; i < num_items_to_read; i++) { - buffer[end + i] = source(); - } - - // move end based on additional items added - end += num_items_to_read; - } - - gcc_assert(0 <= start); - gcc_assert(start <= end); - gcc_assert(end <= (int)buffer.size()); - - gcc_assert(start + n < end); - - // return value at start + n in buffer - return buffer[start + n]; - } - - // TODO: add faster peek current token to remove overhead of conditional branches? - - // Advances start by n + 1. - void skip(int n) { - // Call peek to ensure requested n is actually in queue. - peek(n); - - // Clear values from start to n (inclusive). - for (int i = 0; i < (n + 1); i++) { - // Clear value at index - buffer[start + i] = T(); - } - - // Move start forward by n + 1. - start += (n + 1); - - // Ensure start is not impossible somehow - gcc_assert(0 <= start); - gcc_assert(start <= end); - - // Compact buffer if empty - if (start == end) { - start = end = 0; - } - } - - /* Inserts element at front of vector. Really dirty hack with terrible performance, only use - * when really needed. */ - void insert_at_front(T elem_to_insert) { - // TODO: test as this may not work properly - - // Insert actual element in buffer at start. - buffer.insert(buffer.begin(), 1, elem_to_insert); - - // Increase the end number since added element means all others have shifted one along - end++; - } - - // Replaces the current value in the buffer. Total HACK. - void replace_current_value(T replacement) { - // call peek to ensure value exists - peek(0); - - buffer[start] = replacement; - - // don't move start or end - } - - private: - // Source of tokens for queue. - Source& source; - - // Begin of range in buffer, inclusive. - int start; - // End of range in buffer, exclusive. - int end; - - // Queue buffer. - std::vector<T> buffer; - }; -} - -#endif
\ No newline at end of file +// Buffered queue implementation. Items are of type T, queue source is of type +// Source. +template <typename T, typename Source> class buffered_queue +{ +public: + // Construct empty queue from Source& src. + buffered_queue (Source &src) : source (src), start (0), end (0), buffer () {} + + // Returns token at position start + n (i.e. n tokens ahead). + T peek (int n) + { + // n should not be behind + gcc_assert (n >= 0); + + int num_queued_items = end - start; + int num_items_required = n + 1; + + // if required items go past end of queue, add them to queue + if (num_items_required > num_queued_items) + { + int num_items_to_read = num_items_required - num_queued_items; + + // if queue length + extra items is larger than buffer size, expand + // buffer + if (end + num_items_to_read > (int) buffer.size ()) + { + // Resize the buffer by 1.5x + int new_size = (buffer.size () + num_items_to_read); + new_size += (new_size >> 1); + + // create new queue buffer with new size + std::vector<T> new_queue (new_size); + std::copy (buffer.begin () + start, buffer.begin () + end, + new_queue.begin ()); + start = 0; + end = num_queued_items; + + // swap member buffer and new queue buffer + std::swap (buffer, new_queue); + + // validate that buffer is large enough now + gcc_assert (end + num_queued_items < (int) buffer.size ()); + } + + // iterate through buffer and invoke operator () on source on values + // past original end + for (int i = 0; i < num_items_to_read; i++) + { + buffer[end + i] = source (); + } + + // move end based on additional items added + end += num_items_to_read; + } + + gcc_assert (0 <= start); + gcc_assert (start <= end); + gcc_assert (end <= (int) buffer.size ()); + + gcc_assert (start + n < end); + + // return value at start + n in buffer + return buffer[start + n]; + } + + // TODO: add faster peek current token to remove overhead of conditional + // branches? + + // Advances start by n + 1. + void skip (int n) + { + // Call peek to ensure requested n is actually in queue. + peek (n); + + // Clear values from start to n (inclusive). + for (int i = 0; i < (n + 1); i++) + { + // Clear value at index + buffer[start + i] = T (); + } + + // Move start forward by n + 1. + start += (n + 1); + + // Ensure start is not impossible somehow + gcc_assert (0 <= start); + gcc_assert (start <= end); + + // Compact buffer if empty + if (start == end) + { + start = end = 0; + } + } + + /* Inserts element at front of vector. Really dirty hack with terrible + * performance, only use when really needed. */ + void insert_at_front (T elem_to_insert) + { + // TODO: test as this may not work properly + + // Insert actual element in buffer at start. + buffer.insert (buffer.begin (), 1, elem_to_insert); + + // Increase the end number since added element means all others have shifted + // one along + end++; + } + + // Replaces the current value in the buffer. Total HACK. + void replace_current_value (T replacement) + { + // call peek to ensure value exists + peek (0); + + buffer[start] = replacement; + + // don't move start or end + } + +private: + // Source of tokens for queue. + Source &source; + + // Begin of range in buffer, inclusive. + int start; + // End of range in buffer, exclusive. + int end; + + // Queue buffer. + std::vector<T> buffer; +}; +} // namespace Rust + +#endif diff --git a/gcc/rust/rust-diagnostics.cc b/gcc/rust/rust-diagnostics.cc index d7c6475..8e32f78ae 100644 --- a/gcc/rust/rust-diagnostics.cc +++ b/gcc/rust/rust-diagnostics.cc @@ -1,5 +1,5 @@ // rust-diagnostics.cc -- GCC implementation of rust diagnostics interface. -// Copyright (C) 2016-2019 Free Software Foundation, Inc. +// Copyright (C) 2016-2020 Free Software Foundation, Inc. // Contributed by Than McIntosh, Google. // This file is part of GCC. @@ -22,9 +22,9 @@ #include "rust-diagnostics.h" static std::string -mformat_value() +mformat_value () { - return std::string(xstrerror(errno)); + return std::string (xstrerror (errno)); } // Rewrite a format string to expand any extensions not @@ -32,66 +32,66 @@ mformat_value() // for list of supported format specifiers. static std::string -expand_format(const char* fmt) +expand_format (const char *fmt) { std::stringstream ss; - for (const char* c = fmt; *c; ++c) + for (const char *c = fmt; *c; ++c) { if (*c != '%') - { - ss << *c; - continue; - } + { + ss << *c; + continue; + } c++; switch (*c) - { - case '\0': - { - // malformed format string - rust_unreachable(); - } - case '%': - { - ss << "%"; - break; - } - case 'm': - { - ss << mformat_value(); - break; - } - case '<': - { - ss << rust_open_quote(); - break; - } - case '>': - { - ss << rust_close_quote(); - break; - } - case 'q': - { - ss << rust_open_quote(); - c++; - if (*c == 'm') - { - ss << mformat_value(); - } - else - { - ss << "%" << *c; - } - ss << rust_close_quote(); - break; - } - default: - { - ss << "%" << *c; - } - } + { + case '\0': + { + // malformed format string + rust_unreachable (); + } + case '%': + { + ss << "%"; + break; + } + case 'm': + { + ss << mformat_value (); + break; + } + case '<': + { + ss << rust_open_quote (); + break; + } + case '>': + { + ss << rust_close_quote (); + break; + } + case 'q': + { + ss << rust_open_quote (); + c++; + if (*c == 'm') + { + ss << mformat_value (); + } + else + { + ss << "%" << *c; + } + ss << rust_close_quote (); + break; + } + default: + { + ss << "%" << *c; + } + } } - return ss.str(); + return ss.str (); } // Expand message format specifiers, using a combination of @@ -99,7 +99,9 @@ expand_format(const char* fmt) // to handle regular printf-style formatting. A pragma is being used here to // suppress this warning: // -// warning: function ‘std::__cxx11::string expand_message(const char*, __va_list_tag*)’ might be a candidate for ‘gnu_printf’ format attribute [-Wsuggest-attribute=format] +// warning: function ‘std::__cxx11::string expand_message(const char*, +// __va_list_tag*)’ might be a candidate for ‘gnu_printf’ format attribute +// [-Wsuggest-attribute=format] // // What appears to be happening here is that the checker is deciding that // because of the call to vasprintf() (which has attribute gnu_printf), the @@ -107,109 +109,108 @@ expand_format(const char* fmt) // though there is already an attribute declaration for it. static std::string -expand_message(const char* fmt, va_list ap) RUST_ATTRIBUTE_GCC_DIAG(1,0); +expand_message (const char *fmt, va_list ap) RUST_ATTRIBUTE_GCC_DIAG (1, 0); #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wsuggest-attribute=format" static std::string -expand_message(const char* fmt, va_list ap) +expand_message (const char *fmt, va_list ap) { - char* mbuf = 0; - std::string expanded_fmt = expand_format(fmt); - int nwr = vasprintf(&mbuf, expanded_fmt.c_str(), ap); + char *mbuf = 0; + std::string expanded_fmt = expand_format (fmt); + int nwr = vasprintf (&mbuf, expanded_fmt.c_str (), ap); if (nwr == -1) { // memory allocation failed - rust_be_error_at(Linemap::unknown_location(), - "memory allocation failed in vasprintf"); - rust_assert(0); + rust_be_error_at (Linemap::unknown_location (), + "memory allocation failed in vasprintf"); + rust_assert (0); } - std::string rval = std::string(mbuf); - free(mbuf); + std::string rval = std::string (mbuf); + free (mbuf); return rval; } #pragma GCC diagnostic pop -static const char* cached_open_quote = NULL; -static const char* cached_close_quote = NULL; +static const char *cached_open_quote = NULL; +static const char *cached_close_quote = NULL; -const char* -rust_open_quote() +const char * +rust_open_quote () { if (cached_open_quote == NULL) - rust_be_get_quotechars(&cached_open_quote, &cached_close_quote); + rust_be_get_quotechars (&cached_open_quote, &cached_close_quote); return cached_open_quote; } -const char* -rust_close_quote() +const char * +rust_close_quote () { if (cached_close_quote == NULL) - rust_be_get_quotechars(&cached_open_quote, &cached_close_quote); + rust_be_get_quotechars (&cached_open_quote, &cached_close_quote); return cached_close_quote; } void -rust_error_at(const Location location, const char* fmt, ...) +rust_error_at (const Location location, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - rust_be_error_at(location, expand_message(fmt, ap)); - va_end(ap); + va_start (ap, fmt); + rust_be_error_at (location, expand_message (fmt, ap)); + va_end (ap); } void -rust_warning_at(const Location location, int opt, const char* fmt, ...) +rust_warning_at (const Location location, int opt, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - rust_be_warning_at(location, opt, expand_message(fmt, ap)); - va_end(ap); + va_start (ap, fmt); + rust_be_warning_at (location, opt, expand_message (fmt, ap)); + va_end (ap); } void -rust_fatal_error(const Location location, const char* fmt, ...) +rust_fatal_error (const Location location, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - rust_be_fatal_error(location, expand_message(fmt, ap)); - va_end(ap); + va_start (ap, fmt); + rust_be_fatal_error (location, expand_message (fmt, ap)); + va_end (ap); } void -rust_inform(const Location location, const char* fmt, ...) +rust_inform (const Location location, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - rust_be_inform(location, expand_message(fmt, ap)); - va_end(ap); + va_start (ap, fmt); + rust_be_inform (location, expand_message (fmt, ap)); + va_end (ap); } // rust_debug uses normal printf formatting, not GCC diagnostic formatting. void -rust_debug(const Location location, const char* fmt, ...) +rust_debug (const Location location, const char *fmt, ...) { va_list ap; - va_start(ap, fmt); - char* mbuf = NULL; - int nwr = vasprintf(&mbuf, fmt, ap); - va_end(ap); + va_start (ap, fmt); + char *mbuf = NULL; + int nwr = vasprintf (&mbuf, fmt, ap); + va_end (ap); if (nwr == -1) { - rust_be_error_at(Linemap::unknown_location(), - "memory allocation failed in vasprintf"); - rust_assert(0); + rust_be_error_at (Linemap::unknown_location (), + "memory allocation failed in vasprintf"); + rust_assert (0); } - std::string rval = std::string(mbuf); - free(mbuf); - rust_be_inform(location, rval); + std::string rval = std::string (mbuf); + free (mbuf); + rust_be_inform (location, rval); } - diff --git a/gcc/rust/rust-diagnostics.h b/gcc/rust/rust-diagnostics.h index 0cfbe69..04d48c8 100644 --- a/gcc/rust/rust-diagnostics.h +++ b/gcc/rust/rust-diagnostics.h @@ -6,9 +6,11 @@ #include "rust-linemap.h" #if __GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 1) -#define RUST_ATTRIBUTE_GCC_DIAG(m, n) __attribute__ ((__format__ (__gcc_tdiag__, m, n))) __attribute__ ((__nonnull__ (m))) +#define RUST_ATTRIBUTE_GCC_DIAG(m, n) \ + __attribute__ ((__format__ (__gcc_tdiag__, m, n))) \ + __attribute__ ((__nonnull__ (m))) #else -#define RUST_ATTRIBUTE_GCC_DIAG(m, n) +#define RUST_ATTRIBUTE_GCC_DIAG(m, n) #endif // These declarations define the interface through which the frontend @@ -28,20 +30,26 @@ // All other format specifiers are as defined by 'sprintf'. The final resulting // message is then sent to the back end via rust_be_error_at/rust_be_warning_at. -extern void rust_error_at(const Location, const char* fmt, ...) - RUST_ATTRIBUTE_GCC_DIAG(2,3); -extern void rust_warning_at(const Location, int opt, const char* fmt, ...) - RUST_ATTRIBUTE_GCC_DIAG(3,4); -extern void rust_fatal_error(const Location, const char* fmt, ...) - RUST_ATTRIBUTE_GCC_DIAG(2,3); -extern void rust_inform(const Location, const char* fmt, ...) - RUST_ATTRIBUTE_GCC_DIAG(2,3); +extern void +rust_error_at (const Location, const char *fmt, ...) + RUST_ATTRIBUTE_GCC_DIAG (2, 3); +extern void +rust_warning_at (const Location, int opt, const char *fmt, ...) + RUST_ATTRIBUTE_GCC_DIAG (3, 4); +extern void +rust_fatal_error (const Location, const char *fmt, ...) + RUST_ATTRIBUTE_GCC_DIAG (2, 3); +extern void +rust_inform (const Location, const char *fmt, ...) + RUST_ATTRIBUTE_GCC_DIAG (2, 3); // These interfaces provide a way for the front end to ask for // the open/close quote characters it should use when formatting // diagnostics (warnings, errors). -extern const char* rust_open_quote(); -extern const char* rust_close_quote(); +extern const char * +rust_open_quote (); +extern const char * +rust_close_quote (); // These interfaces are used by utilities above to pass warnings and // errors (once format specifiers have been expanded) to the back end, @@ -49,12 +57,15 @@ extern const char* rust_close_quote(); // instead use the equivalent routines above. The back end is required to // implement these routines. -extern void rust_be_error_at(const Location, const std::string& errmsg); -extern void rust_be_warning_at(const Location, int opt, - const std::string& warningmsg); -extern void rust_be_fatal_error(const Location, const std::string& errmsg); -extern void rust_be_inform(const Location, const std::string& infomsg); -extern void rust_be_get_quotechars(const char** open_quote, - const char** close_quote); +extern void +rust_be_error_at (const Location, const std::string &errmsg); +extern void +rust_be_warning_at (const Location, int opt, const std::string &warningmsg); +extern void +rust_be_fatal_error (const Location, const std::string &errmsg); +extern void +rust_be_inform (const Location, const std::string &infomsg); +extern void +rust_be_get_quotechars (const char **open_quote, const char **close_quote); #endif // !defined(RUST_DIAGNOSTICS_H) diff --git a/gcc/rust/rust-gcc.cc b/gcc/rust/rust-gcc.cc index 47c3657..6699b47 100644 --- a/gcc/rust/rust-gcc.cc +++ b/gcc/rust/rust-gcc.cc @@ -1,5 +1,5 @@ // rust-gcc.cc -- Rust frontend to gcc IR. -// Copyright (C) 2011-2019 Free Software Foundation, Inc. +// Copyright (C) 2011-2020 Free Software Foundation, Inc. // Contributed by Ian Lance Taylor, Google. // forked from gccgo @@ -428,6 +428,7 @@ private: tree convert_tree (tree, tree, Location); private: +<<<<<<< HEAD static const int builtin_const = 1 << 0; static const int builtin_noreturn = 1 << 1; static const int builtin_novops = 1 << 2; @@ -436,6 +437,13 @@ private: const char *libname, tree fntype, int flags); // A mapping of the GCC built-ins exposed to GCCRust. +======= + void define_builtin (built_in_function bcode, const char *name, + const char *libname, tree fntype, bool const_p, + bool noreturn_p); + + // A mapping of the GCC built-ins exposed to GCCGo. +>>>>>>> 12e994a7967... Fix indentation std::map<std::string, Bfunction *> builtin_functions_; }; @@ -456,22 +464,42 @@ Gcc_backend::Gcc_backend () tree t = this->integer_type (true, BITS_PER_UNIT)->get_tree (); tree p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_1, "__sync_fetch_and_add_1", +<<<<<<< HEAD NULL, build_function_type_list (t, p, t, NULL_TREE), 0); +======= + NULL, build_function_type_list (t, p, t, NULL_TREE), + false, false); +>>>>>>> 12e994a7967... Fix indentation t = this->integer_type (true, BITS_PER_UNIT * 2)->get_tree (); p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_2, "__sync_fetch_and_add_2", +<<<<<<< HEAD NULL, build_function_type_list (t, p, t, NULL_TREE), 0); +======= + NULL, build_function_type_list (t, p, t, NULL_TREE), + false, false); +>>>>>>> 12e994a7967... Fix indentation t = this->integer_type (true, BITS_PER_UNIT * 4)->get_tree (); p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_4, "__sync_fetch_and_add_4", +<<<<<<< HEAD NULL, build_function_type_list (t, p, t, NULL_TREE), 0); +======= + NULL, build_function_type_list (t, p, t, NULL_TREE), + false, false); +>>>>>>> 12e994a7967... Fix indentation t = this->integer_type (true, BITS_PER_UNIT * 8)->get_tree (); p = build_pointer_type (build_qualified_type (t, TYPE_QUAL_VOLATILE)); this->define_builtin (BUILT_IN_SYNC_ADD_AND_FETCH_8, "__sync_fetch_and_add_8", +<<<<<<< HEAD NULL, build_function_type_list (t, p, t, NULL_TREE), 0); +======= + NULL, build_function_type_list (t, p, t, NULL_TREE), + false, false); +>>>>>>> 12e994a7967... Fix indentation // We use __builtin_expect for magic import functions. this->define_builtin (BUILT_IN_EXPECT, "__builtin_expect", NULL, @@ -479,7 +507,11 @@ Gcc_backend::Gcc_backend () long_integer_type_node, long_integer_type_node, NULL_TREE), +<<<<<<< HEAD builtin_const); +======= + true, false); +>>>>>>> 12e994a7967... Fix indentation // We use __builtin_memcmp for struct comparisons. this->define_builtin (BUILT_IN_MEMCMP, "__builtin_memcmp", "memcmp", @@ -487,53 +519,86 @@ Gcc_backend::Gcc_backend () const_ptr_type_node, const_ptr_type_node, size_type_node, NULL_TREE), +<<<<<<< HEAD 0); +======= + false, false); +>>>>>>> 12e994a7967... Fix indentation // We use __builtin_memmove for copying data. this->define_builtin (BUILT_IN_MEMMOVE, "__builtin_memmove", "memmove", build_function_type_list (void_type_node, ptr_type_node, const_ptr_type_node, size_type_node, NULL_TREE), +<<<<<<< HEAD 0); +======= + false, false); +>>>>>>> 12e994a7967... Fix indentation // We use __builtin_memset for zeroing data. this->define_builtin (BUILT_IN_MEMSET, "__builtin_memset", "memset", build_function_type_list (void_type_node, ptr_type_node, integer_type_node, size_type_node, NULL_TREE), +<<<<<<< HEAD 0); +======= + false, false); +>>>>>>> 12e994a7967... Fix indentation // Used by runtime/internal/sys and math/bits. this->define_builtin (BUILT_IN_CTZ, "__builtin_ctz", "ctz", build_function_type_list (integer_type_node, unsigned_type_node, NULL_TREE), +<<<<<<< HEAD builtin_const); +======= + true, false); +>>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_CTZLL, "__builtin_ctzll", "ctzll", build_function_type_list (integer_type_node, long_long_unsigned_type_node, NULL_TREE), +<<<<<<< HEAD builtin_const); +======= + true, false); +>>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_CLZ, "__builtin_clz", "clz", build_function_type_list (integer_type_node, unsigned_type_node, NULL_TREE), +<<<<<<< HEAD builtin_const); +======= + true, false); +>>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_CLZLL, "__builtin_clzll", "clzll", build_function_type_list (integer_type_node, long_long_unsigned_type_node, NULL_TREE), +<<<<<<< HEAD builtin_const); +======= + true, false); +>>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_POPCOUNT, "__builtin_popcount", "popcount", build_function_type_list (integer_type_node, unsigned_type_node, NULL_TREE), +<<<<<<< HEAD builtin_const); +======= + true, false); +>>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_POPCOUNTLL, "__builtin_popcountll", "popcountll", build_function_type_list (integer_type_node, long_long_unsigned_type_node, NULL_TREE), +<<<<<<< HEAD builtin_const); this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16", build_function_type_list (uint16_type_node, @@ -547,6 +612,21 @@ Gcc_backend::Gcc_backend () build_function_type_list (uint64_type_node, uint64_type_node, NULL_TREE), builtin_const); +======= + true, false); + this->define_builtin (BUILT_IN_BSWAP16, "__builtin_bswap16", "bswap16", + build_function_type_list (uint16_type_node, + uint16_type_node, NULL_TREE), + true, false); + this->define_builtin (BUILT_IN_BSWAP32, "__builtin_bswap32", "bswap32", + build_function_type_list (uint32_type_node, + uint32_type_node, NULL_TREE), + true, false); + this->define_builtin (BUILT_IN_BSWAP64, "__builtin_bswap64", "bswap64", + build_function_type_list (uint64_type_node, + uint64_type_node, NULL_TREE), + true, false); +>>>>>>> 12e994a7967... Fix indentation // We provide some functions for the math library. tree math_function_type @@ -561,6 +641,7 @@ Gcc_backend::Gcc_backend () = build_function_type_list (long_double_type_node, long_double_type_node, long_double_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ACOS, "__builtin_acos", "acos", +<<<<<<< HEAD math_function_type, builtin_const); this->define_builtin (BUILT_IN_ACOSL, "__builtin_acosl", "acosl", math_function_type_long, builtin_const); @@ -604,15 +685,65 @@ Gcc_backend::Gcc_backend () math_function_type_two, builtin_const); this->define_builtin (BUILT_IN_FMODL, "__builtin_fmodl", "fmodl", math_function_type_long_two, builtin_const); +======= + math_function_type, true, false); + this->define_builtin (BUILT_IN_ACOSL, "__builtin_acosl", "acosl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_ASIN, "__builtin_asin", "asin", + math_function_type, true, false); + this->define_builtin (BUILT_IN_ASINL, "__builtin_asinl", "asinl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_ATAN, "__builtin_atan", "atan", + math_function_type, true, false); + this->define_builtin (BUILT_IN_ATANL, "__builtin_atanl", "atanl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_ATAN2, "__builtin_atan2", "atan2", + math_function_type_two, true, false); + this->define_builtin (BUILT_IN_ATAN2L, "__builtin_atan2l", "atan2l", + math_function_type_long_two, true, false); + this->define_builtin (BUILT_IN_CEIL, "__builtin_ceil", "ceil", + math_function_type, true, false); + this->define_builtin (BUILT_IN_CEILL, "__builtin_ceill", "ceill", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_COS, "__builtin_cos", "cos", + math_function_type, true, false); + this->define_builtin (BUILT_IN_COSL, "__builtin_cosl", "cosl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_EXP, "__builtin_exp", "exp", + math_function_type, true, false); + this->define_builtin (BUILT_IN_EXPL, "__builtin_expl", "expl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_EXPM1, "__builtin_expm1", "expm1", + math_function_type, true, false); + this->define_builtin (BUILT_IN_EXPM1L, "__builtin_expm1l", "expm1l", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_FABS, "__builtin_fabs", "fabs", + math_function_type, true, false); + this->define_builtin (BUILT_IN_FABSL, "__builtin_fabsl", "fabsl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_FLOOR, "__builtin_floor", "floor", + math_function_type, true, false); + this->define_builtin (BUILT_IN_FLOORL, "__builtin_floorl", "floorl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_FMOD, "__builtin_fmod", "fmod", + math_function_type_two, true, false); + this->define_builtin (BUILT_IN_FMODL, "__builtin_fmodl", "fmodl", + math_function_type_long_two, true, false); +>>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_LDEXP, "__builtin_ldexp", "ldexp", build_function_type_list (double_type_node, double_type_node, integer_type_node, NULL_TREE), +<<<<<<< HEAD builtin_const); +======= + true, false); +>>>>>>> 12e994a7967... Fix indentation this->define_builtin (BUILT_IN_LDEXPL, "__builtin_ldexpl", "ldexpl", build_function_type_list (long_double_type_node, long_double_type_node, integer_type_node, NULL_TREE), +<<<<<<< HEAD builtin_const); this->define_builtin (BUILT_IN_LOG, "__builtin_log", "log", math_function_type, builtin_const); @@ -646,11 +777,47 @@ Gcc_backend::Gcc_backend () math_function_type, builtin_const); this->define_builtin (BUILT_IN_TRUNCL, "__builtin_truncl", "truncl", math_function_type_long, builtin_const); +======= + true, false); + this->define_builtin (BUILT_IN_LOG, "__builtin_log", "log", + math_function_type, true, false); + this->define_builtin (BUILT_IN_LOGL, "__builtin_logl", "logl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_LOG1P, "__builtin_log1p", "log1p", + math_function_type, true, false); + this->define_builtin (BUILT_IN_LOG1PL, "__builtin_log1pl", "log1pl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_LOG10, "__builtin_log10", "log10", + math_function_type, true, false); + this->define_builtin (BUILT_IN_LOG10L, "__builtin_log10l", "log10l", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_LOG2, "__builtin_log2", "log2", + math_function_type, true, false); + this->define_builtin (BUILT_IN_LOG2L, "__builtin_log2l", "log2l", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_SIN, "__builtin_sin", "sin", + math_function_type, true, false); + this->define_builtin (BUILT_IN_SINL, "__builtin_sinl", "sinl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_SQRT, "__builtin_sqrt", "sqrt", + math_function_type, true, false); + this->define_builtin (BUILT_IN_SQRTL, "__builtin_sqrtl", "sqrtl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_TAN, "__builtin_tan", "tan", + math_function_type, true, false); + this->define_builtin (BUILT_IN_TANL, "__builtin_tanl", "tanl", + math_function_type_long, true, false); + this->define_builtin (BUILT_IN_TRUNC, "__builtin_trunc", "trunc", + math_function_type, true, false); + this->define_builtin (BUILT_IN_TRUNCL, "__builtin_truncl", "truncl", + math_function_type_long, true, false); +>>>>>>> 12e994a7967... Fix indentation // We use __builtin_return_address in the thunk we build for // functions which call recover, and for runtime.getcallerpc. t = build_function_type_list (ptr_type_node, unsigned_type_node, NULL_TREE); this->define_builtin (BUILT_IN_RETURN_ADDRESS, "__builtin_return_address", +<<<<<<< HEAD NULL, t, 0); // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp. @@ -662,94 +829,176 @@ Gcc_backend::Gcc_backend () this->define_builtin ( BUILT_IN_EXTRACT_RETURN_ADDR, "__builtin_extract_return_addr", NULL, build_function_type_list (ptr_type_node, ptr_type_node, NULL_TREE), 0); +======= + NULL, t, false, false); + + // The runtime calls __builtin_dwarf_cfa for runtime.getcallersp. + t = build_function_type_list (ptr_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_DWARF_CFA, "__builtin_dwarf_cfa", NULL, t, + false, false); + + // The runtime calls __builtin_extract_return_addr when recording + // the address to which a function returns. + this->define_builtin (BUILT_IN_EXTRACT_RETURN_ADDR, + "__builtin_extract_return_addr", NULL, + build_function_type_list (ptr_type_node, ptr_type_node, + NULL_TREE), + false, false); +>>>>>>> 12e994a7967... Fix indentation // The compiler uses __builtin_trap for some exception handling // cases. this->define_builtin (BUILT_IN_TRAP, "__builtin_trap", NULL, build_function_type (void_type_node, void_list_node), +<<<<<<< HEAD builtin_noreturn); +======= + false, true); +>>>>>>> 12e994a7967... Fix indentation // The runtime uses __builtin_prefetch. this->define_builtin (BUILT_IN_PREFETCH, "__builtin_prefetch", NULL, build_varargs_function_type_list (void_type_node, const_ptr_type_node, NULL_TREE), +<<<<<<< HEAD builtin_novops); +======= + false, false); +>>>>>>> 12e994a7967... Fix indentation // The compiler uses __builtin_unreachable for cases that cannot // occur. this->define_builtin (BUILT_IN_UNREACHABLE, "__builtin_unreachable", NULL, build_function_type (void_type_node, void_list_node), +<<<<<<< HEAD builtin_const | builtin_noreturn); +======= + true, true); +>>>>>>> 12e994a7967... Fix indentation // We provide some atomic functions. t = build_function_type_list (uint32_type_node, ptr_type_node, integer_type_node, NULL_TREE); +<<<<<<< HEAD this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t, 0); t = build_function_type_list (uint64_type_node, ptr_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t, 0); +======= + this->define_builtin (BUILT_IN_ATOMIC_LOAD_4, "__atomic_load_4", NULL, t, + false, false); + + t = build_function_type_list (uint64_type_node, ptr_type_node, + integer_type_node, NULL_TREE); + this->define_builtin (BUILT_IN_ATOMIC_LOAD_8, "__atomic_load_8", NULL, t, + false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (void_type_node, ptr_type_node, uint32_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_STORE_4, "__atomic_store_4", NULL, t, +<<<<<<< HEAD 0); +======= + false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (void_type_node, ptr_type_node, uint64_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_STORE_8, "__atomic_store_8", NULL, t, +<<<<<<< HEAD 0); +======= + false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (uint32_type_node, ptr_type_node, uint32_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_4, "__atomic_exchange_4", NULL, +<<<<<<< HEAD t, 0); +======= + t, false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (uint64_type_node, ptr_type_node, uint64_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_EXCHANGE_8, "__atomic_exchange_8", NULL, +<<<<<<< HEAD t, 0); +======= + t, false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (boolean_type_node, ptr_type_node, ptr_type_node, uint32_type_node, boolean_type_node, integer_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_4, +<<<<<<< HEAD "__atomic_compare_exchange_4", NULL, t, 0); +======= + "__atomic_compare_exchange_4", NULL, t, false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (boolean_type_node, ptr_type_node, ptr_type_node, uint64_type_node, boolean_type_node, integer_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_COMPARE_EXCHANGE_8, +<<<<<<< HEAD "__atomic_compare_exchange_8", NULL, t, 0); +======= + "__atomic_compare_exchange_8", NULL, t, false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (uint32_type_node, ptr_type_node, uint32_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_4, "__atomic_add_fetch_4", +<<<<<<< HEAD NULL, t, 0); +======= + NULL, t, false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (uint64_type_node, ptr_type_node, uint64_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_ADD_FETCH_8, "__atomic_add_fetch_8", +<<<<<<< HEAD NULL, t, 0); +======= + NULL, t, false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (unsigned_char_type_node, ptr_type_node, unsigned_char_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_AND_FETCH_1, "__atomic_and_fetch_1", +<<<<<<< HEAD NULL, t, 0); this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", NULL, t, 0); +======= + NULL, t, false, false); + this->define_builtin (BUILT_IN_ATOMIC_FETCH_AND_1, "__atomic_fetch_and_1", + NULL, t, false, false); +>>>>>>> 12e994a7967... Fix indentation t = build_function_type_list (unsigned_char_type_node, ptr_type_node, unsigned_char_type_node, integer_type_node, NULL_TREE); this->define_builtin (BUILT_IN_ATOMIC_OR_FETCH_1, "__atomic_or_fetch_1", NULL, +<<<<<<< HEAD t, 0); this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL, t, 0); +======= + t, false, false); + this->define_builtin (BUILT_IN_ATOMIC_FETCH_OR_1, "__atomic_fetch_or_1", NULL, + t, false, false); +>>>>>>> 12e994a7967... Fix indentation } // Get an unnamed integer type. @@ -1138,7 +1387,11 @@ Gcc_backend::named_type (const std::string &name, Btype *btype, // The middle-end expects a basic type to have a name. In Rust every // basic type will have a name. The first time we see a basic type, +<<<<<<< HEAD // give it whatever Rust name we have at this point. +======= + // give it whatever Go name we have at this point. +>>>>>>> 12e994a7967... Fix indentation if (TYPE_NAME (type) == NULL_TREE && location.gcc_location () == BUILTINS_LOCATION && (TREE_CODE (type) == INTEGER_TYPE || TREE_CODE (type) == REAL_TYPE @@ -1584,7 +1837,11 @@ Gcc_backend::unary_expression (Operator op, Bexpression *expr, enum tree_code code; switch (op) { +<<<<<<< HEAD + case OPERATOR_MINUS: { +======= case OPERATOR_MINUS: { +>>>>>>> 12e994a7967... Fix indentation tree computed_type = excess_precision_type (type_tree); if (computed_type != NULL_TREE) { @@ -1916,8 +2173,13 @@ Gcc_backend::call_expression (Bfunction *, // containing fcn for call // This is to support builtin math functions when using 80387 math. tree excess_type = NULL_TREE; if (optimize && TREE_CODE (fndecl) == FUNCTION_DECL +<<<<<<< HEAD && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL) && DECL_IS_UNDECLARED_BUILTIN (fndecl) && nargs > 0 +======= + && fndecl_built_in_p (fndecl, BUILT_IN_NORMAL) && DECL_IS_BUILTIN (fndecl) + && nargs > 0 +>>>>>>> 12e994a7967... Fix indentation && ((SCALAR_FLOAT_TYPE_P (rettype) && SCALAR_FLOAT_TYPE_P (TREE_TYPE (args[0]))) || (COMPLEX_FLOAT_TYPE_P (rettype) @@ -2420,11 +2682,19 @@ Gcc_backend::non_zero_size_type (tree type) DECL_CONTEXT (field) = type; TYPE_FIELDS (type) = field; layout_type (type); +<<<<<<< HEAD rust_non_zero_struct = type; +======= + go_non_zero_struct = type; +>>>>>>> 12e994a7967... Fix indentation } return rust_non_zero_struct; +<<<<<<< HEAD + case ARRAY_TYPE: { +======= case ARRAY_TYPE: { +>>>>>>> 12e994a7967... Fix indentation tree element_type = non_zero_size_type (TREE_TYPE (type)); return build_array_type_nelts (element_type, 1); } @@ -2532,7 +2802,11 @@ Gcc_backend::global_variable_set_init (Bvariable *var, Bexpression *expr) if (symtab_node::get (var_decl) && symtab_node::get (var_decl)->implicit_section) { +<<<<<<< HEAD set_decl_section_name (var_decl, (const char *) NULL); +======= + set_decl_section_name (var_decl, NULL); +>>>>>>> 12e994a7967... Fix indentation resolve_unique_section (var_decl, compute_reloc_for_constant (expr_tree), 1); } @@ -2647,14 +2921,22 @@ Gcc_backend::temporary_variable (Bfunction *function, Bblock *bblock, else push_cfun (DECL_STRUCT_FUNCTION (decl)); +<<<<<<< HEAD var = create_tmp_var (type_tree, "RUSTTMP"); +======= + var = create_tmp_var (type_tree, "GOTMP"); +>>>>>>> 12e994a7967... Fix indentation pop_cfun (); } else { gcc_assert (bblock != NULL); var = build_decl (location.gcc_location (), VAR_DECL, +<<<<<<< HEAD create_tmp_var_name ("RUSTTMP"), type_tree); +======= + create_tmp_var_name ("GOTMP"), type_tree); +>>>>>>> 12e994a7967... Fix indentation DECL_ARTIFICIAL (var) = 1; DECL_IGNORED_P (var) = 1; TREE_USED (var) = 1; @@ -3048,15 +3330,24 @@ Gcc_backend::function (Btype *fntype, const std::string &name, if (pos == name.length ()) { struct cl_optimization cur_opts; +<<<<<<< HEAD cl_optimization_save (&cur_opts, &global_options, &global_options_set); +======= + cl_optimization_save (&cur_opts, &global_options); +>>>>>>> 12e994a7967... Fix indentation global_options.x_optimize_size = 1; global_options.x_optimize_fast = 0; global_options.x_optimize_debug = 0; DECL_FUNCTION_SPECIFIC_OPTIMIZATION (decl) +<<<<<<< HEAD = build_optimization_node (&global_options, &global_options_set); cl_optimization_restore (&global_options, &global_options_set, &cur_opts); +======= + = build_optimization_node (&global_options); + cl_optimization_restore (&global_options, &cur_opts); +>>>>>>> 12e994a7967... Fix indentation } } diff --git a/gcc/rust/rust-lang.cc b/gcc/rust/rust-lang.cc index c3ae4da..66895dc 100644 --- a/gcc/rust/rust-lang.cc +++ b/gcc/rust/rust-lang.cc @@ -16,27 +16,32 @@ #include "common/common-target.h" #include <mpfr.h> -// note: header files must be in this order or else forward declarations don't work properly. Kinda -// dumb system, but have to live with it. clang-format seems to mess it up -/* Order: config, system, coretypes, target, tree, gimple-expr, diagnostic, opts, fold-const, - * gimplify, stor-layout, debug, convert, langhooks, langhooks-def, common-target */ +// note: header files must be in this order or else forward declarations don't +// work properly. Kinda dumb system, but have to live with it. clang-format +// seems to mess it up +/* Order: config, system, coretypes, target, tree, gimple-expr, diagnostic, + * opts, fold-const, gimplify, stor-layout, debug, convert, langhooks, + * langhooks-def, common-target */ // FIXME: test saving intellisense #include "options.h" // version check to stop compiling if c++ isn't c++11 or higher #if __cplusplus < 201103 -#error \ +#error \ "GCC Rust frontend requires C++11 or higher. You can compile the g++ frontend first and then compile the Rust frontend using that." #endif // TODO: is this best way to do it? Is it allowed? (should be) /* General TODOs: - * - maybe convert all raw pointer-returning/passing functions that conceptually return a unique - * pointer actually return a unique pointer. i.e. parse methods and constructors for AST objects. - * make_unique should probably be avoided to keep C++11 compatibility. - * - convert all copies of expensive-to-copy (deep copy) AST objects into moves, if possible. Don't - * remove clone functionality - it may be required for e.g. HIR conversion. */ + * - maybe convert all raw pointer-returning/passing functions that + * conceptually return a unique pointer actually return a unique pointer. i.e. + * parse methods and constructors for AST objects. make_unique should probably + * be avoided to keep C++11 compatibility. + * - convert all copies of expensive-to-copy (deep copy) AST objects into + * moves, if possible. Don't + * remove clone functionality - it may be required for e.g. HIR conversion. + */ #include "rust-system.h" #include "rust-parse.h" @@ -45,32 +50,40 @@ #include "rust-target.h" // Language-dependent contents of a type. GTY() mark used for garbage collector. -struct GTY(()) lang_type { - char dummy; +struct GTY (()) lang_type +{ + char dummy; }; // Language-dependent contents of a decl. -struct GTY(()) lang_decl { - char dummy; +struct GTY (()) lang_decl +{ + char dummy; }; -// Language-dependent contents of an identifier. This must include a tree_identifier. -struct GTY(()) lang_identifier { - struct tree_identifier common; +// Language-dependent contents of an identifier. This must include a +// tree_identifier. +struct GTY (()) lang_identifier +{ + struct tree_identifier common; }; // The resulting tree type. -union GTY((desc("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), - chain_next( +union GTY (( + desc ("TREE_CODE (&%h.generic) == IDENTIFIER_NODE"), + chain_next ( "CODE_CONTAINS_STRUCT (TREE_CODE (&%h.generic), " - "TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) lang_tree_node { - union tree_node GTY((tag("0"), desc("tree_node_structure (&%h)"))) generic; - struct lang_identifier GTY((tag("1"))) identifier; + "TS_COMMON) ? ((union lang_tree_node *) TREE_CHAIN (&%h.generic)) : NULL"))) + lang_tree_node +{ + union tree_node GTY ((tag ("0"), desc ("tree_node_structure (&%h)"))) generic; + struct lang_identifier GTY ((tag ("1"))) identifier; }; // We don't use language_function. -struct GTY(()) language_function { - int dummy; +struct GTY (()) language_function +{ + int dummy; }; // Kinda HACK-ish - store parsing session as static variable @@ -84,124 +97,153 @@ void rust_add_target_info(const char* key, const char* value) { /* Language hooks. */ /* Initial lang hook called (possibly), used for initialisation. - * Must call build_common_tree_nodes, set_sizetype, build_common_tree_nodes_2, and - * build_common_builtin_nodes, as well as set global variable void_list_node. - * Apparently called after option handling? */ -static bool grs_langhook_init(void) { - /* Something to do with this: - This allows the code in d-builtins.cc to not have to worry about - converting (C signed char *) to (D char *) for string arguments of - built-in functions. The parameter (signed_char = false) specifies - whether char is signed. */ - build_common_tree_nodes(false); - - // Creates a new TREE_LIST node with purpose NULL_TREE and value void_type_node - void_list_node = build_tree_list(NULL_TREE, void_type_node); - - // Builds built-ins for middle-end after all front-end built-ins are already instantiated - build_common_builtin_nodes(); - - mpfr_set_default_prec(128); - - using_eh_for_cleanups(); - - // initialise compiler session - session.init(); - - return true; + * Must call build_common_tree_nodes, set_sizetype, build_common_tree_nodes_2, + * and build_common_builtin_nodes, as well as set global variable + * void_list_node. Apparently called after option handling? */ +static bool +grs_langhook_init (void) +{ + /* Something to do with this: + This allows the code in d-builtins.cc to not have to worry about + converting (C signed char *) to (D char *) for string arguments of + built-in functions. The parameter (signed_char = false) specifies + whether char is signed. */ + build_common_tree_nodes (false); + + // Creates a new TREE_LIST node with purpose NULL_TREE and value + // void_type_node + void_list_node = build_tree_list (NULL_TREE, void_type_node); + + // Builds built-ins for middle-end after all front-end built-ins are already + // instantiated + build_common_builtin_nodes (); + + mpfr_set_default_prec (128); + + using_eh_for_cleanups (); + + // initialise compiler session + session.init (); + + return true; } -/* The option mask (something to do with options for specific frontends or something). */ -static unsigned int grs_langhook_option_lang_mask(void) { - return CL_Rust; +/* The option mask (something to do with options for specific frontends or + * something). */ +static unsigned int +grs_langhook_option_lang_mask (void) +{ + return CL_Rust; } /* Initialize the options structure. */ -static void grs_langhook_init_options_struct(struct gcc_options* opts) { - // nothing yet - used by frontends to change specific options for the language - session.init_options(); +static void +grs_langhook_init_options_struct (struct gcc_options *opts) +{ + // nothing yet - used by frontends to change specific options for the language + session.init_options (); } -/* Main entry point for front-end, apparently. Finds input file names in global vars in_fnames and - * num_in_fnames. From this, frontend can take over and do actual parsing and initial compilation. - * This function must create a complete parse tree in a global var, and then return. +/* Main entry point for front-end, apparently. Finds input file names in global + * vars in_fnames and num_in_fnames. From this, frontend can take over and do + * actual parsing and initial compilation. This function must create a complete + * parse tree in a global var, and then return. * * Some consider this the "start of compilation". */ -static void grs_langhook_parse_file(void) { - fprintf(stderr, "Preparing to parse files. \n"); +static void +grs_langhook_parse_file (void) +{ + fprintf (stderr, "Preparing to parse files. \n"); - // grs_parse_files(num_in_fnames, in_fnames); - session.parse_files(num_in_fnames, in_fnames); + // grs_parse_files(num_in_fnames, in_fnames); + session.parse_files (num_in_fnames, in_fnames); } -/* Seems to get the exact type for a specific type - e.g. for scalar float with 32-bit bitsize, it - * returns float, and for 64-bit bitsize, it returns double. Used to map RTL nodes to machine modes or - * something like that. */ -static tree grs_langhook_type_for_mode(machine_mode mode, int unsignedp) { - // TODO: change all this later to match rustc types - if (mode == TYPE_MODE(float_type_node)) - return float_type_node; - - if (mode == TYPE_MODE(double_type_node)) - return double_type_node; - - if (mode == TYPE_MODE(intQI_type_node)) // quarter integer mode - single byte treated as integer - return unsignedp ? unsigned_intQI_type_node : intQI_type_node; - if (mode == TYPE_MODE(intHI_type_node)) // half integer mode - two-byte integer - return unsignedp ? unsigned_intHI_type_node : intHI_type_node; - if (mode == TYPE_MODE(intSI_type_node)) // single integer mode - four-byte integer - return unsignedp ? unsigned_intSI_type_node : intSI_type_node; - if (mode == TYPE_MODE(intDI_type_node)) // double integer mode - eight-byte integer - return unsignedp ? unsigned_intDI_type_node : intDI_type_node; - if (mode == TYPE_MODE(intTI_type_node)) // tetra integer mode - 16-byte integer - return unsignedp ? unsigned_intTI_type_node : intTI_type_node; - - if (mode == TYPE_MODE(integer_type_node)) - return unsignedp ? unsigned_type_node : integer_type_node; - - if (mode == TYPE_MODE(long_integer_type_node)) - return unsignedp ? long_unsigned_type_node : long_integer_type_node; - - if (mode == TYPE_MODE(long_long_integer_type_node)) - return unsignedp ? long_long_unsigned_type_node : long_long_integer_type_node; - - if (COMPLEX_MODE_P(mode)) { - if (mode == TYPE_MODE(complex_float_type_node)) - return complex_float_type_node; - if (mode == TYPE_MODE(complex_double_type_node)) - return complex_double_type_node; - if (mode == TYPE_MODE(complex_long_double_type_node)) - return complex_long_double_type_node; - if (mode == TYPE_MODE(complex_integer_type_node) && !unsignedp) - return complex_integer_type_node; +/* Seems to get the exact type for a specific type - e.g. for scalar float with + * 32-bit bitsize, it returns float, and for 64-bit bitsize, it returns double. + * Used to map RTL nodes to machine modes or something like that. */ +static tree +grs_langhook_type_for_mode (machine_mode mode, int unsignedp) +{ + // TODO: change all this later to match rustc types + if (mode == TYPE_MODE (float_type_node)) + return float_type_node; + + if (mode == TYPE_MODE (double_type_node)) + return double_type_node; + + if (mode == TYPE_MODE (intQI_type_node)) // quarter integer mode - single byte + // treated as integer + return unsignedp ? unsigned_intQI_type_node : intQI_type_node; + if (mode + == TYPE_MODE (intHI_type_node)) // half integer mode - two-byte integer + return unsignedp ? unsigned_intHI_type_node : intHI_type_node; + if (mode + == TYPE_MODE (intSI_type_node)) // single integer mode - four-byte integer + return unsignedp ? unsigned_intSI_type_node : intSI_type_node; + if (mode + == TYPE_MODE ( + intDI_type_node)) // double integer mode - eight-byte integer + return unsignedp ? unsigned_intDI_type_node : intDI_type_node; + if (mode + == TYPE_MODE (intTI_type_node)) // tetra integer mode - 16-byte integer + return unsignedp ? unsigned_intTI_type_node : intTI_type_node; + + if (mode == TYPE_MODE (integer_type_node)) + return unsignedp ? unsigned_type_node : integer_type_node; + + if (mode == TYPE_MODE (long_integer_type_node)) + return unsignedp ? long_unsigned_type_node : long_integer_type_node; + + if (mode == TYPE_MODE (long_long_integer_type_node)) + return unsignedp ? long_long_unsigned_type_node + : long_long_integer_type_node; + + if (COMPLEX_MODE_P (mode)) + { + if (mode == TYPE_MODE (complex_float_type_node)) + return complex_float_type_node; + if (mode == TYPE_MODE (complex_double_type_node)) + return complex_double_type_node; + if (mode == TYPE_MODE (complex_long_double_type_node)) + return complex_long_double_type_node; + if (mode == TYPE_MODE (complex_integer_type_node) && !unsignedp) + return complex_integer_type_node; } - /* gcc_unreachable */ - return NULL; + /* gcc_unreachable */ + return NULL; } -/* This appears to be used for creating different types for different bit sizes (e.g. int and long). - * Also, the Go frontend calls this from type_for_mode to determine the type from a specific bitsize - * for integer types. - * FIXME: change this when working on AST-GENERIC conversion to allow the full range of Rust type - * sizes. */ -static tree grs_langhook_type_for_size( - unsigned int bits ATTRIBUTE_UNUSED, int unsignedp ATTRIBUTE_UNUSED) { - gcc_unreachable(); - return NULL_TREE; - // nothing at the moment, but change later +/* This appears to be used for creating different types for different bit sizes + * (e.g. int and long). Also, the Go frontend calls this from type_for_mode to + * determine the type from a specific bitsize for integer types. + * FIXME: change this when working on AST-GENERIC conversion to allow the full + * range of Rust type sizes. */ +static tree +grs_langhook_type_for_size (unsigned int bits ATTRIBUTE_UNUSED, + int unsignedp ATTRIBUTE_UNUSED) +{ + gcc_unreachable (); + return NULL_TREE; + // nothing at the moment, but change later } // Record a builtin function. We just ignore builtin functions. -static tree grs_langhook_builtin_function(tree decl ATTRIBUTE_UNUSED) { - return decl; +static tree +grs_langhook_builtin_function (tree decl ATTRIBUTE_UNUSED) +{ + return decl; } -/* Return true if we are in the global binding level (which is never, apparently). */ -static bool grs_langhook_global_bindings_p(void) { - // return current_function_decl == NULL_TREE; - // gcc_unreachable(); - // return true; - return false; +/* Return true if we are in the global binding level (which is never, + * apparently). */ +static bool +grs_langhook_global_bindings_p (void) +{ + // return current_function_decl == NULL_TREE; + // gcc_unreachable(); + // return true; + return false; } /* Push a declaration into the current binding level. We can't @@ -210,72 +252,85 @@ static bool grs_langhook_global_bindings_p(void) { this is used is to record a decl which is to be returned by getdecls, and we could implement it for that purpose if necessary. */ -static tree grs_langhook_pushdecl(tree decl ATTRIBUTE_UNUSED) { - gcc_unreachable(); - return NULL; +static tree +grs_langhook_pushdecl (tree decl ATTRIBUTE_UNUSED) +{ + gcc_unreachable (); + return NULL; } /* This hook is used to get the current list of declarations as trees. We don't support that; instead we use the write_globals hook. This can't simply crash because it is called by -gstabs. */ -static tree grs_langhook_getdecls(void) { - // gcc_unreachable(); - return NULL; +static tree +grs_langhook_getdecls (void) +{ + // gcc_unreachable(); + return NULL; } // Handle Rust-specific options. Return false if nothing happened. -static bool grs_langhook_handle_option(size_t scode, const char* arg, HOST_WIDE_INT value, - int kind ATTRIBUTE_UNUSED, location_t loc ATTRIBUTE_UNUSED, - const struct cl_option_handlers* handlers ATTRIBUTE_UNUSED) { - // Convert integer code to lang.opt enum codes with names. - enum opt_code code = (enum opt_code)scode; - // used to store whether results of various stuff are successful - // bool ret = true; - - // delegate to session manager - return session.handle_option(code, arg, value, kind, loc, handlers); - - // Handles options as listed in lang.opt. - /*switch (code) { - case OPT_I: - // TODO: add search path - break; - case OPT_L: - // TODO: add library link path or something - break; - case OPT_frust_dump: - // enable dump and return whether this was successful - ret = rust_enable_dump(arg) ? true : false; - break; - // no option handling for -o - default: - // return 1 to indicate option is valid - break; - } - - return ret;*/ +static bool +grs_langhook_handle_option ( + size_t scode, const char *arg, HOST_WIDE_INT value, int kind ATTRIBUTE_UNUSED, + location_t loc ATTRIBUTE_UNUSED, + const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED) +{ + // Convert integer code to lang.opt enum codes with names. + enum opt_code code = (enum opt_code) scode; + // used to store whether results of various stuff are successful + // bool ret = true; + + // delegate to session manager + return session.handle_option (code, arg, value, kind, loc, handlers); + + // Handles options as listed in lang.opt. + /*switch (code) { + case OPT_I: + // TODO: add search path + break; + case OPT_L: + // TODO: add library link path or something + break; + case OPT_frust_dump: + // enable dump and return whether this was successful + ret = rust_enable_dump(arg) ? true : false; + break; + // no option handling for -o + default: + // return 1 to indicate option is valid + break; + } + + return ret;*/ } /* Run after parsing options. */ -static bool grs_langhook_post_options(const char** pfilename ATTRIBUTE_UNUSED) { - // can be used to override other options if required +static bool +grs_langhook_post_options (const char **pfilename ATTRIBUTE_UNUSED) +{ + // can be used to override other options if required - // satisfies an assert in init_excess_precision in toplev.c - if (flag_excess_precision/*_cmdline*/ == EXCESS_PRECISION_DEFAULT) - flag_excess_precision/*_cmdline*/ = EXCESS_PRECISION_STANDARD; + // satisfies an assert in init_excess_precision in toplev.c + if (flag_excess_precision /*_cmdline*/ == EXCESS_PRECISION_DEFAULT) + flag_excess_precision /*_cmdline*/ = EXCESS_PRECISION_STANDARD; - /* Returning false means that the backend should be used. */ - return false; + /* Returning false means that the backend should be used. */ + return false; } -/* Rust-specific gimplification. May need to gimplify e.g. CALL_EXPR_STATIC_CHAIN */ -static int grs_langhook_gimplify_expr(tree* expr_p ATTRIBUTE_UNUSED, - gimple_seq* pre_p ATTRIBUTE_UNUSED, gimple_seq* post_p ATTRIBUTE_UNUSED) { - if (TREE_CODE (*expr_p) == CALL_EXPR +/* Rust-specific gimplification. May need to gimplify e.g. + * CALL_EXPR_STATIC_CHAIN */ +static int +grs_langhook_gimplify_expr (tree *expr_p ATTRIBUTE_UNUSED, + gimple_seq *pre_p ATTRIBUTE_UNUSED, + gimple_seq *post_p ATTRIBUTE_UNUSED) +{ + if (TREE_CODE (*expr_p) == CALL_EXPR && CALL_EXPR_STATIC_CHAIN (*expr_p) != NULL_TREE) - gimplify_expr (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p, post_p, - is_gimple_val, fb_rvalue); - return GS_UNHANDLED; + gimplify_expr (&CALL_EXPR_STATIC_CHAIN (*expr_p), pre_p, post_p, + is_gimple_val, fb_rvalue); + return GS_UNHANDLED; } static tree @@ -293,8 +348,7 @@ grs_langhook_eh_personality (void) tree convert (tree type, tree expr) { - if (type == error_mark_node - || expr == error_mark_node + if (type == error_mark_node || expr == error_mark_node || TREE_TYPE (expr) == error_mark_node) return error_mark_node; @@ -327,7 +381,7 @@ convert (tree type, tree expr) /* FIXME: This is a hack to preserve trees that we create from the garbage collector. */ -static GTY(()) tree rust_gc_root; +static GTY (()) tree rust_gc_root; void rust_preserve_from_gc (tree t) @@ -343,9 +397,9 @@ rust_localize_identifier (const char *ident) return identifier_to_locale (ident); } -/* The language hooks data structure. This is the main interface between the GCC front-end - * and the GCC middle-end/back-end. A list of language hooks could be found in - * <gcc>/langhooks.h +/* The language hooks data structure. This is the main interface between the GCC + * front-end and the GCC middle-end/back-end. A list of language hooks could be + * found in <gcc>/langhooks.h */ #undef LANG_HOOKS_NAME #undef LANG_HOOKS_INIT @@ -370,9 +424,11 @@ rust_localize_identifier (const char *ident) #define LANG_HOOKS_INIT_OPTIONS_STRUCT grs_langhook_init_options_struct #define LANG_HOOKS_HANDLE_OPTION grs_langhook_handle_option #define LANG_HOOKS_POST_OPTIONS grs_langhook_post_options -/* Main lang-hook, apparently. Finds input file names in global vars in_fnames and num_in_fnames - * From this, frontend can take over and do actual parsing and initial compilation. - * This hook must create a complete parse tree in a global var, and then return. */ +/* Main lang-hook, apparently. Finds input file names in global vars in_fnames + * and num_in_fnames From this, frontend can take over and do actual parsing and + * initial compilation. + * This hook must create a complete parse tree in a global var, and then return. + */ #define LANG_HOOKS_PARSE_FILE grs_langhook_parse_file #define LANG_HOOKS_TYPE_FOR_MODE grs_langhook_type_for_mode #define LANG_HOOKS_TYPE_FOR_SIZE grs_langhook_type_for_size diff --git a/gcc/rust/rust-linemap.cc b/gcc/rust/rust-linemap.cc index aa75c6e..fef4603 100644 --- a/gcc/rust/rust-linemap.cc +++ b/gcc/rust/rust-linemap.cc @@ -2,83 +2,68 @@ #include "rust-linemap.h" - // This class implements the Linemap interface defined by the // frontend. class Gcc_linemap : public Linemap { - public: - Gcc_linemap() - : Linemap(), - in_file_(false) - { } +public: + Gcc_linemap () : Linemap (), in_file_ (false) {} - void - start_file(const char* file_name, unsigned int line_begin); + void start_file (const char *file_name, unsigned int line_begin); - void - start_line(unsigned int line_number, unsigned int line_size); + void start_line (unsigned int line_number, unsigned int line_size); - Location - get_location(unsigned int column); + Location get_location (unsigned int column); - void - stop(); + void stop (); - std::string - to_string(Location); + std::string to_string (Location); - std::string - location_file(Location); + std::string location_file (Location); - int - location_line(Location); + int location_line (Location); - protected: - Location - get_predeclared_location(); +protected: + Location get_predeclared_location (); - Location - get_unknown_location(); + Location get_unknown_location (); - bool - is_predeclared(Location); + bool is_predeclared (Location); - bool - is_unknown(Location); + bool is_unknown (Location); - private: +private: // Whether we are currently reading a file. bool in_file_; }; -Linemap* Linemap::instance_ = NULL; +Linemap *Linemap::instance_ = NULL; // Start getting locations from a new file. void -Gcc_linemap::start_file(const char *file_name, unsigned line_begin) +Gcc_linemap::start_file (const char *file_name, unsigned line_begin) { if (this->in_file_) - linemap_add(line_table, LC_LEAVE, 0, NULL, 0); - linemap_add(line_table, LC_ENTER, 0, file_name, line_begin); + linemap_add (line_table, LC_LEAVE, 0, NULL, 0); + linemap_add (line_table, LC_ENTER, 0, file_name, line_begin); this->in_file_ = true; } // Stringify a location std::string -Gcc_linemap::to_string(Location location) +Gcc_linemap::to_string (Location location) { const line_map_ordinary *lmo; location_t resolved_location; // Screen out unknown and predeclared locations; produce output // only for simple file:line locations. - resolved_location = - linemap_resolve_location (line_table, location.gcc_location(), - LRK_SPELLING_LOCATION, &lmo); + resolved_location + = linemap_resolve_location (line_table, location.gcc_location (), + LRK_SPELLING_LOCATION, &lmo); if (lmo == NULL || resolved_location < RESERVED_LOCATION_COUNT) return ""; const char *path = LINEMAP_FILE (lmo); @@ -87,87 +72,87 @@ Gcc_linemap::to_string(Location location) // Strip the source file down to the base file, to reduce clutter. std::stringstream ss; - ss << lbasename(path) << ":" << SOURCE_LINE (lmo, location.gcc_location()); - return ss.str(); + ss << lbasename (path) << ":" << SOURCE_LINE (lmo, location.gcc_location ()); + return ss.str (); } // Return the file name for a given location. std::string -Gcc_linemap::location_file(Location loc) +Gcc_linemap::location_file (Location loc) { - return LOCATION_FILE(loc.gcc_location()); + return LOCATION_FILE (loc.gcc_location ()); } // Return the line number for a given location. int -Gcc_linemap::location_line(Location loc) +Gcc_linemap::location_line (Location loc) { - return LOCATION_LINE(loc.gcc_location()); + return LOCATION_LINE (loc.gcc_location ()); } // Stop getting locations. void -Gcc_linemap::stop() +Gcc_linemap::stop () { - linemap_add(line_table, LC_LEAVE, 0, NULL, 0); + linemap_add (line_table, LC_LEAVE, 0, NULL, 0); this->in_file_ = false; } // Start a new line. void -Gcc_linemap::start_line(unsigned lineno, unsigned linesize) +Gcc_linemap::start_line (unsigned lineno, unsigned linesize) { - linemap_line_start(line_table, lineno, linesize); + linemap_line_start (line_table, lineno, linesize); } // Get a location. Location -Gcc_linemap::get_location(unsigned column) +Gcc_linemap::get_location (unsigned column) { - return Location(linemap_position_for_column(line_table, column)); + return Location (linemap_position_for_column (line_table, column)); } // Get the unknown location. Location -Gcc_linemap::get_unknown_location() +Gcc_linemap::get_unknown_location () { - return Location(UNKNOWN_LOCATION); + return Location (UNKNOWN_LOCATION); } // Get the predeclared location. Location -Gcc_linemap::get_predeclared_location() +Gcc_linemap::get_predeclared_location () { - return Location(BUILTINS_LOCATION); + return Location (BUILTINS_LOCATION); } // Return whether a location is the predeclared location. bool -Gcc_linemap::is_predeclared(Location loc) +Gcc_linemap::is_predeclared (Location loc) { - return loc.gcc_location() == BUILTINS_LOCATION; + return loc.gcc_location () == BUILTINS_LOCATION; } // Return whether a location is the unknown location. bool -Gcc_linemap::is_unknown(Location loc) +Gcc_linemap::is_unknown (Location loc) { - return loc.gcc_location() == UNKNOWN_LOCATION; + return loc.gcc_location () == UNKNOWN_LOCATION; } // Return the Linemap to use for the gcc backend. -Linemap* -rust_get_linemap() +Linemap * +rust_get_linemap () { return new Gcc_linemap; } diff --git a/gcc/rust/rust-linemap.h b/gcc/rust/rust-linemap.h index 03c60f5..73e6a0b 100644 --- a/gcc/rust/rust-linemap.h +++ b/gcc/rust/rust-linemap.h @@ -22,147 +22,130 @@ // The Linemap class is a pure abstract interface, plus some static // convenience functions. The backend must implement the interface. -/* TODO: probably better to replace linemap implementation as pure abstract interface with some sort of - * compile-time switch (macros or maybe templates if doable without too much extra annoyance) as to the - * definition of the methods or whatever. This is to improve performance, as virtual function calls would +/* TODO: probably better to replace linemap implementation as pure abstract + * interface with some sort of compile-time switch (macros or maybe templates if + * doable without too much extra annoyance) as to the definition of the methods + * or whatever. This is to improve performance, as virtual function calls would * otherwise have to be made in tight loops like in the lexer. */ class Linemap { - public: - Linemap() +public: + Linemap () { // Only one instance of Linemap is allowed to exist. - rust_assert(Linemap::instance_ == NULL); + rust_assert (Linemap::instance_ == NULL); Linemap::instance_ = this; } - virtual - ~Linemap() { Linemap::instance_ = NULL; } + virtual ~Linemap () { Linemap::instance_ = NULL; } // Subsequent Location values will come from the file named // FILE_NAME, starting at LINE_BEGIN. Normally LINE_BEGIN will be // 0, but it will be non-zero if the Rust source has a //line comment. - virtual void - start_file(const char* file_name, unsigned int line_begin) = 0; + virtual void start_file (const char *file_name, unsigned int line_begin) = 0; // Subsequent Location values will come from the line LINE_NUMBER, // in the current file. LINE_SIZE is the size of the line in bytes. // This will normally be called for every line in a source file. - virtual void - start_line(unsigned int line_number, unsigned int line_size) = 0; + virtual void start_line (unsigned int line_number, unsigned int line_size) + = 0; // Get a Location representing column position COLUMN on the current // line in the current file. - virtual Location - get_location(unsigned int column) = 0; + virtual Location get_location (unsigned int column) = 0; // Stop generating Location values. This will be called after all // input files have been read, in case any cleanup is required. - virtual void - stop() = 0; + virtual void stop () = 0; // Produce a human-readable description of a Location, e.g. // "foo.rust:10". Returns an empty string for predeclared, builtin or // unknown locations. - virtual std::string - to_string(Location) = 0; + virtual std::string to_string (Location) = 0; // Return the file name for a given location. - virtual std::string - location_file(Location) = 0; + virtual std::string location_file (Location) = 0; // Return the line number for a given location. - virtual int - location_line(Location) = 0; + virtual int location_line (Location) = 0; - protected: +protected: // Return a special Location used for predeclared identifiers. This // Location should be different from that for any actual source // file. This location will be used for various different types, // functions, and objects created by the frontend. - virtual Location - get_predeclared_location() = 0; + virtual Location get_predeclared_location () = 0; // Return a special Location which indicates that no actual location // is known. This is used for undefined objects and for errors. - virtual Location - get_unknown_location() = 0; + virtual Location get_unknown_location () = 0; // Return whether the argument is the Location returned by // get_predeclared_location. - virtual bool - is_predeclared(Location) = 0; + virtual bool is_predeclared (Location) = 0; // Return whether the argument is the Location returned by // get_unknown_location. - virtual bool - is_unknown(Location) = 0; + virtual bool is_unknown (Location) = 0; // The single existing instance of Linemap. static Linemap *instance_; - public: +public: // Following are convenience static functions, which allow us to // access some virtual functions without explicitly passing around // an instance of Linemap. // Return the special Location used for predeclared identifiers. - static Location - predeclared_location() + static Location predeclared_location () { - rust_assert(Linemap::instance_ != NULL); - return Linemap::instance_->get_predeclared_location(); + rust_assert (Linemap::instance_ != NULL); + return Linemap::instance_->get_predeclared_location (); } // Return the special Location used when no location is known. - static Location - unknown_location() + static Location unknown_location () { - rust_assert(Linemap::instance_ != NULL); - return Linemap::instance_->get_unknown_location(); + rust_assert (Linemap::instance_ != NULL); + return Linemap::instance_->get_unknown_location (); } // Return whether the argument is the special location used for // predeclared identifiers. - static bool - is_predeclared_location(Location loc) + static bool is_predeclared_location (Location loc) { - rust_assert(Linemap::instance_ != NULL); - return Linemap::instance_->is_predeclared(loc); + rust_assert (Linemap::instance_ != NULL); + return Linemap::instance_->is_predeclared (loc); } // Return whether the argument is the special location used when no // location is known. - static bool - is_unknown_location(Location loc) + static bool is_unknown_location (Location loc) { - rust_assert(Linemap::instance_ != NULL); - return Linemap::instance_->is_unknown(loc); + rust_assert (Linemap::instance_ != NULL); + return Linemap::instance_->is_unknown (loc); } // Produce a human-readable description of a Location. - static std::string - location_to_string(Location loc) + static std::string location_to_string (Location loc) { - rust_assert(Linemap::instance_ != NULL); - return Linemap::instance_->to_string(loc); + rust_assert (Linemap::instance_ != NULL); + return Linemap::instance_->to_string (loc); } // Return the file name of a location. - static std::string - location_to_file(Location loc) + static std::string location_to_file (Location loc) { - rust_assert(Linemap::instance_ != NULL); - return Linemap::instance_->location_file(loc); + rust_assert (Linemap::instance_ != NULL); + return Linemap::instance_->location_file (loc); } // Return line number of a location. - static int - location_to_line(Location loc) + static int location_to_line (Location loc) { - rust_assert(Linemap::instance_ != NULL); - return Linemap::instance_->location_line(loc); + rust_assert (Linemap::instance_ != NULL); + return Linemap::instance_->location_line (loc); } }; diff --git a/gcc/rust/rust-location.h b/gcc/rust/rust-location.h index 0515f68..575fa83 100644 --- a/gcc/rust/rust-location.h +++ b/gcc/rust/rust-location.h @@ -9,63 +9,54 @@ class Location { - public: - Location() - : gcc_loc_(UNKNOWN_LOCATION) - { } +public: + Location () : gcc_loc_ (UNKNOWN_LOCATION) {} - explicit Location(location_t loc) - : gcc_loc_(loc) - { } + explicit Location (location_t loc) : gcc_loc_ (loc) {} - location_t - gcc_location() const - { return gcc_loc_; } + location_t gcc_location () const { return gcc_loc_; } - Location - operator+=(location_t rhs) { + Location operator+= (location_t rhs) + { gcc_loc_ += rhs; return *this; } - Location - operator-=(location_t rhs) { + Location operator-= (location_t rhs) + { gcc_loc_ -= rhs; return *this; } - bool - operator==(location_t rhs) { - return rhs == gcc_loc_; - } + bool operator== (location_t rhs) { return rhs == gcc_loc_; } - private: +private: location_t gcc_loc_; }; // The Rust frontend requires the ability to compare Locations. inline bool -operator<(Location loca, Location locb) +operator< (Location loca, Location locb) { - return loca.gcc_location() < locb.gcc_location(); + return loca.gcc_location () < locb.gcc_location (); } inline bool -operator==(Location loca, Location locb) +operator== (Location loca, Location locb) { - return loca.gcc_location() == locb.gcc_location(); + return loca.gcc_location () == locb.gcc_location (); } -inline Location -operator+(Location lhs, location_t rhs) +inline Location +operator+ (Location lhs, location_t rhs) { lhs += rhs; return lhs; } -inline Location -operator-(Location lhs, location_t rhs) +inline Location +operator- (Location lhs, location_t rhs) { lhs -= rhs; return lhs; diff --git a/gcc/rust/rust-object-export.c b/gcc/rust/rust-object-export.c index c985035..e59d3fb 100644 --- a/gcc/rust/rust-object-export.c +++ b/gcc/rust/rust-object-export.c @@ -1,21 +1,21 @@ /* rust-backend.c -- Rust frontend interface to gcc backend. - Copyright (C) 2010-2019 Free Software Foundation, Inc. + Copyright (C) 2010-2020 Free Software Foundation, Inc. -This file is part of GCC. + 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 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. + 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/>. */ + 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/>. */ // FIXME: doesn't this duplicate lots of code from rust-backend.c? Is one meant to be a replacement? @@ -30,7 +30,7 @@ along with GCC; see the file COPYING3. If not see #include "simple-object.h" #include "stor-layout.h" #include "intl.h" -#include "output.h" /* for assemble_string */ +#include "output.h" /* for assemble_string */ #include "common/common-target.h" // satisfy intellisense @@ -111,8 +111,8 @@ rust_write_export_data (const char *bytes, unsigned int size) { gcc_assert (targetm_common.have_named_sections); sec = get_section (RUST_EXPORT_SECTION_NAME, - TARGET_AIX ? SECTION_EXCLUDE : SECTION_DEBUG, - NULL); + TARGET_AIX ? SECTION_EXCLUDE : SECTION_DEBUG, + NULL); } switch_to_section (sec); @@ -132,7 +132,7 @@ rust_write_export_data (const char *bytes, unsigned int size) const char * rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, - int *perr) + int *perr) { simple_object_read *sobj; const char *errmsg; @@ -146,20 +146,20 @@ rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, *plen = 0; sobj = simple_object_start_read (fd, offset, RUST_EXPORT_SEGMENT_NAME, - &errmsg, perr); + &errmsg, perr); if (sobj == NULL) { /* If we get an error here, just pretend that we didn't find any - export data. This is the right thing to do if the error is - that the file was not recognized as an object file. This - will ignore file I/O errors, but it's not too big a deal - because we will wind up giving some other error later. */ + export data. This is the right thing to do if the error is + that the file was not recognized as an object file. This + will ignore file I/O errors, but it's not too big a deal + because we will wind up giving some other error later. */ return NULL; } found = simple_object_find_section (sobj, RUST_EXPORT_SECTION_NAME, - &sec_offset, &sec_length, - &errmsg, perr); + &sec_offset, &sec_length, + &errmsg, perr); simple_object_release_read (sobj); if (!found) return errmsg; diff --git a/gcc/rust/rust-object-export.h b/gcc/rust/rust-object-export.h index d511078..5ec63e8 100644 --- a/gcc/rust/rust-object-export.h +++ b/gcc/rust/rust-object-export.h @@ -9,4 +9,4 @@ rust_read_export_data (int fd, off_t offset, char **pbuf, size_t *plen, extern void rust_write_export_data (const char *bytes, unsigned int size); -#endif // RUST_OBJECT_EXPORT_H
\ No newline at end of file +#endif // RUST_OBJECT_EXPORT_H diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index a52e1a5..2247519 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -13,656 +13,799 @@ #include <algorithm> -extern Linemap* rust_get_linemap(); +extern Linemap * +rust_get_linemap (); namespace Rust { - // Simple wrapper for FILE* that simplifies destruction. - struct RAIIFile { - FILE* file; - - RAIIFile(const char* filename) : file(fopen(filename, "r")) {} - - ~RAIIFile() { - fclose(file); - } - }; - - // Implicitly enable a target_feature (and recursively enable dependencies). - void Session::implicitly_enable_feature(::std::string feature_name) { - // TODO: is this really required since features added would be complete via target spec? - - if (!options.target_data.has_key_value_pair("target_data", feature_name)) { - // if feature has dependencies, enable them - if (feature_name == "aes") { - implicitly_enable_feature("sse2"); - } else if (feature_name == "avx") { - implicitly_enable_feature("sse4.2"); - } else if (feature_name == "avx2") { - implicitly_enable_feature("avx"); - } else if (feature_name == "fma") { - implicitly_enable_feature("avx"); - } else if (feature_name == "pclmulqdq") { - implicitly_enable_feature("sse2"); - } else if (feature_name == "sha") { - implicitly_enable_feature("sse2"); - } else if (feature_name == "sse2") { - implicitly_enable_feature("sse"); - } else if (feature_name == "sse3") { - implicitly_enable_feature("sse2"); - } else if (feature_name == "sse4.1") { - implicitly_enable_feature("sse3"); - } else if (feature_name == "sse4.2") { - implicitly_enable_feature("sse4.1"); - } else if (feature_name == "ssse3") { - implicitly_enable_feature("sse3"); - } - - options.target_data.insert_key_value_pair("target_feature", ::std::move(feature_name)); - } +// Simple wrapper for FILE* that simplifies destruction. +struct RAIIFile +{ + FILE *file; + + RAIIFile (const char *filename) : file (fopen (filename, "r")) {} + + ~RAIIFile () { fclose (file); } +}; + +// Implicitly enable a target_feature (and recursively enable dependencies). +void +Session::implicitly_enable_feature (::std::string feature_name) +{ + // TODO: is this really required since features added would be complete via + // target spec? + + if (!options.target_data.has_key_value_pair ("target_data", feature_name)) + { + // if feature has dependencies, enable them + if (feature_name == "aes") + { + implicitly_enable_feature ("sse2"); + } + else if (feature_name == "avx") + { + implicitly_enable_feature ("sse4.2"); + } + else if (feature_name == "avx2") + { + implicitly_enable_feature ("avx"); + } + else if (feature_name == "fma") + { + implicitly_enable_feature ("avx"); + } + else if (feature_name == "pclmulqdq") + { + implicitly_enable_feature ("sse2"); + } + else if (feature_name == "sha") + { + implicitly_enable_feature ("sse2"); + } + else if (feature_name == "sse2") + { + implicitly_enable_feature ("sse"); + } + else if (feature_name == "sse3") + { + implicitly_enable_feature ("sse2"); + } + else if (feature_name == "sse4.1") + { + implicitly_enable_feature ("sse3"); + } + else if (feature_name == "sse4.2") + { + implicitly_enable_feature ("sse4.1"); + } + else if (feature_name == "ssse3") + { + implicitly_enable_feature ("sse3"); + } + + options.target_data.insert_key_value_pair ("target_feature", + ::std::move (feature_name)); } +} - // Meant to enable all target features. As this will be done by target hook, this method's - // deprecated. - void Session::enable_features() { - bool has_target_crt_static = false; - const char* target = "PLACEHOLDER"; - - fprintf(stderr, "ERROR: Somewhere in call chain Session::enable_features is called.\n"); - - if (has_target_crt_static) { - // enable "crt-static" attribute - } - - /* TODO: do this via target hook. have one for each target that implicitly enables the - * features for that platform. Would probably have to make custom target hook. */ - - /* - if (target == "x86" || target == "x86_64") { - if (TARGET_ISA_AES) { - // enable aes, implicitly enable sse2 - implicitly_enable_feature("aes"); - } - - if (TARGET_ISA_AVX) { - // enable avx, implicitly enable sse4.2 - implicitly_enable_feature("sse4.2"); - } - - if (TARGET_ISA_AVX2) { - // enable avx2, implicitly enable avx - implicitly_enable_feature("avx"); - } - - if (TARGET_ISA_BMI) { - // enable bmi1 - implicitly_enable_feature("bmi1"); - } - - if (TARGET_ISA_BMI2) { - // enable bmi2 - implicitly_enable_feature("bmi2"); - } - - if (TARGET_ISA_FMA) { - // enable fma, implicitly enable avx - implicitly_enable_feature("fma"); - } - - if (TARGET_ISA_FXSR) { - // enable fxsr - implicitly_enable_feature("fxsr"); - } - - if (TARGET_ISA_LZCNT) { - // enable lzcnt - implicitly_enable_feature("lzcnt"); - } - - if (TARGET_ISA_VPCLMULQDQ) { - // enable pclmulqdq, implicitly enable sse2 - implicitly_enable_feature("pclmulqdq"); - } - - if (TARGET_ISA_POPCNT) { - // enable popcnt - implicitly_enable_feature("popcnt"); - } - - if (TARGET_ISA_RDRND) { - // enable rdrand - implicitly_enable_feature("rdrand"); - } - - if (TARGET_ISA_RDSEED) { - // enable rdseed - implicitly_enable_feature("rdseed"); - } - - if (TARGET_ISA_SHA) { - // enable sha, implicitly enable sse2 - implicitly_enable_feature("sha"); - } - - if (TARGET_ISA_SSE) { - // enable sse - implicitly_enable_feature("sse"); - } - - if (TARGET_ISA_SSE2) { - // enable sse2, implicitly enable sse - implicitly_enable_feature("sse2"); - } - - if (TARGET_ISA_SSE3) { - // enable sse3, implicitly enable sse2 - implicitly_enable_feature("sse3"); - } - - if (TARGET_ISA_SSE4_1) { - // enable sse4.1, implicitly enable sse3 - implicitly_enable_feature("sse4.1"); - } - - if (TARGET_ISA_SSE4_2) { - // enable sse4.2, implicitly enable sse4.1 - implicitly_enable_feature("sse4.2"); - } - - if (TARGET_ISA_SSSE3) { - // enable ssse3, implicitly enable sse3 - implicitly_enable_feature("ssse3"); - } - - if (TARGET_ISA_XSAVE) { - // enable xsave - implicitly_enable_feature("xsave"); - } - - if (TARGET_ISA_XSAVEC) { - // enable xsavec - implicitly_enable_feature("xsavec"); - } - - if (TARGET_ISA_XSAVEOPT) { - // enable xsaveopt - implicitly_enable_feature("xsaveopt"); - } - - if (TARGET_ISA_XSAVES) { - // enable xsaves - implicitly_enable_feature("xsaves"); - } - } - options.target_data.features.shrink_to_fit(); - ::std::sort(options.target_data.features.begin(), options.target_data.features.end());*/ +// Meant to enable all target features. As this will be done by target hook, +// this method's deprecated. +void +Session::enable_features () +{ + bool has_target_crt_static = false; + const char *target = "PLACEHOLDER"; + + fprintf ( + stderr, + "ERROR: Somewhere in call chain Session::enable_features is called.\n"); + + if (has_target_crt_static) + { + // enable "crt-static" attribute } - void Session::init() { -# define builtin_rust_info(KEY, VALUE) rust_add_target_info (KEY, VALUE) + /* TODO: do this via target hook. have one for each target that implicitly + * enables the + * features for that platform. Would probably have to make custom target hook. + */ + + /* + if (target == "x86" || target == "x86_64") { + if (TARGET_ISA_AES) { + // enable aes, implicitly enable sse2 + implicitly_enable_feature("aes"); + } + + if (TARGET_ISA_AVX) { + // enable avx, implicitly enable sse4.2 + implicitly_enable_feature("sse4.2"); + } + + if (TARGET_ISA_AVX2) { + // enable avx2, implicitly enable avx + implicitly_enable_feature("avx"); + } + + if (TARGET_ISA_BMI) { + // enable bmi1 + implicitly_enable_feature("bmi1"); + } + + if (TARGET_ISA_BMI2) { + // enable bmi2 + implicitly_enable_feature("bmi2"); + } + + if (TARGET_ISA_FMA) { + // enable fma, implicitly enable avx + implicitly_enable_feature("fma"); + } + + if (TARGET_ISA_FXSR) { + // enable fxsr + implicitly_enable_feature("fxsr"); + } + + if (TARGET_ISA_LZCNT) { + // enable lzcnt + implicitly_enable_feature("lzcnt"); + } + + if (TARGET_ISA_VPCLMULQDQ) { + // enable pclmulqdq, implicitly enable sse2 + implicitly_enable_feature("pclmulqdq"); + } + + if (TARGET_ISA_POPCNT) { + // enable popcnt + implicitly_enable_feature("popcnt"); + } + + if (TARGET_ISA_RDRND) { + // enable rdrand + implicitly_enable_feature("rdrand"); + } + + if (TARGET_ISA_RDSEED) { + // enable rdseed + implicitly_enable_feature("rdseed"); + } + + if (TARGET_ISA_SHA) { + // enable sha, implicitly enable sse2 + implicitly_enable_feature("sha"); + } + + if (TARGET_ISA_SSE) { + // enable sse + implicitly_enable_feature("sse"); + } + + if (TARGET_ISA_SSE2) { + // enable sse2, implicitly enable sse + implicitly_enable_feature("sse2"); + } + + if (TARGET_ISA_SSE3) { + // enable sse3, implicitly enable sse2 + implicitly_enable_feature("sse3"); + } + + if (TARGET_ISA_SSE4_1) { + // enable sse4.1, implicitly enable sse3 + implicitly_enable_feature("sse4.1"); + } + + if (TARGET_ISA_SSE4_2) { + // enable sse4.2, implicitly enable sse4.1 + implicitly_enable_feature("sse4.2"); + } + + if (TARGET_ISA_SSSE3) { + // enable ssse3, implicitly enable sse3 + implicitly_enable_feature("ssse3"); + } + + if (TARGET_ISA_XSAVE) { + // enable xsave + implicitly_enable_feature("xsave"); + } + + if (TARGET_ISA_XSAVEC) { + // enable xsavec + implicitly_enable_feature("xsavec"); + } + + if (TARGET_ISA_XSAVEOPT) { + // enable xsaveopt + implicitly_enable_feature("xsaveopt"); + } + + if (TARGET_ISA_XSAVES) { + // enable xsaves + implicitly_enable_feature("xsaves"); + } + } + options.target_data.features.shrink_to_fit(); + ::std::sort(options.target_data.features.begin(), + options.target_data.features.end());*/ +} + +void +Session::init () +{ + // nothing yet +} + +// Initialise default options. Actually called before handle_option, unlike init +// itself. +void +Session::init_options () +{ + options.dump_option = CompileOptions::NO_DUMP; +} - // initialise target hooks - targetrustm.rust_cpu_info(); - targetrustm.rust_os_info(); - -#undef builtin_rust_info +// Handle option selection. +bool +Session::handle_option ( + enum opt_code code, const char *arg, HOST_WIDE_INT value ATTRIBUTE_UNUSED, + int kind ATTRIBUTE_UNUSED, location_t loc ATTRIBUTE_UNUSED, + const struct cl_option_handlers *handlers ATTRIBUTE_UNUSED) +{ + // used to store whether results of various stuff are successful + bool ret = true; + + // Handles options as listed in lang.opt. + switch (code) + { + case OPT_I: + // TODO: add search path + break; + case OPT_L: + // TODO: add library link path or something + break; + case OPT_frust_dump_: + // enable dump and return whether this was successful + if (arg != NULL) + { + ret = enable_dump (::std::string (arg)); + } + else + { + ret = false; + } + break; + // no option handling for -o + default: + // return 1 to indicate option is valid + break; } - // Initialise default options. Actually called before handle_option, unlike init itself. - void Session::init_options() { - options.dump_option = CompileOptions::NO_DUMP; + return ret; +} + +/* Enables a certain dump depending on the name passed in. Returns true if name + * is valid, false otherwise. */ +bool +Session::enable_dump (::std::string arg) +{ + // FIXME: change dumping algorithm when new non-inhibiting dump system is + // created + if (arg == "all") + { + error_at ( + UNKNOWN_LOCATION, + "dumping all is not supported as of now. choose 'lex' or 'parse'"); + return false; + } + else if (arg == "lex") + { + options.dump_option = CompileOptions::LEXER_DUMP; + } + else if (arg == "parse") + { + options.dump_option = CompileOptions::PARSER_AST_DUMP; + } + else if (arg == "register_plugins") + { + options.dump_option = CompileOptions::REGISTER_PLUGINS_DUMP; + } + else if (arg == "injection") + { + options.dump_option = CompileOptions::INJECTION_DUMP; } + else if (arg == "expansion") + { + options.dump_option = CompileOptions::EXPANSION_DUMP; + } + else if (arg == "name_resolution") + { + options.dump_option = CompileOptions::NAME_RESOLUTION_DUMP; + } + else if (arg == "") + { + error_at (UNKNOWN_LOCATION, + "dump option was not given a name. choose 'lex' or 'parse'"); + return false; + } + else + { + error_at (UNKNOWN_LOCATION, + "dump option '%s' was unrecognised. choose 'lex' or 'parse'", + arg.c_str ()); + return false; + } + return true; +} - // Handle option selection. - bool Session::handle_option(enum opt_code code, const char* arg, - HOST_WIDE_INT value ATTRIBUTE_UNUSED, int kind ATTRIBUTE_UNUSED, - location_t loc ATTRIBUTE_UNUSED, const struct cl_option_handlers* handlers ATTRIBUTE_UNUSED) { - // used to store whether results of various stuff are successful - bool ret = true; - - // Handles options as listed in lang.opt. - switch (code) { - case OPT_I: - // TODO: add search path - break; - case OPT_L: - // TODO: add library link path or something - break; - case OPT_frust_dump_: - // enable dump and return whether this was successful - if (arg != NULL) { - ret = enable_dump(::std::string(arg)); - } else { - ret = false; - } - break; - // no option handling for -o - default: - // return 1 to indicate option is valid - break; - } - - return ret; +/* Actual main entry point for front-end. Called from langhook to parse files. + */ +void +Session::parse_files (int num_files, const char **files) +{ + for (int i = 0; i < num_files; i++) + { + parse_file (files[i]); } + // TODO: should semantic analysis be dealed with here? or per file? for now, + // per-file. +} - /* Enables a certain dump depending on the name passed in. Returns true if name is valid, false - * otherwise. */ - bool Session::enable_dump(::std::string arg) { - // FIXME: change dumping algorithm when new non-inhibiting dump system is created - if (arg == "all") { - error_at( - UNKNOWN_LOCATION, "dumping all is not supported as of now. choose 'lex' or 'parse'"); - return false; - } else if (arg == "lex") { - options.dump_option = CompileOptions::LEXER_DUMP; - } else if (arg == "parse") { - options.dump_option = CompileOptions::PARSER_AST_DUMP; - } else if (arg == "register_plugins") { - options.dump_option = CompileOptions::REGISTER_PLUGINS_DUMP; - } else if (arg == "injection") { - options.dump_option = CompileOptions::INJECTION_DUMP; - } else if (arg == "expansion") { - options.dump_option = CompileOptions::EXPANSION_DUMP; - } else if (arg == "name_resolution") { - options.dump_option = CompileOptions::NAME_RESOLUTION_DUMP; - } else if (arg == "") { - error_at(UNKNOWN_LOCATION, "dump option was not given a name. choose 'lex' or 'parse'"); - return false; - } else { - error_at(UNKNOWN_LOCATION, "dump option '%s' was unrecognised. choose 'lex' or 'parse'", - arg.c_str()); - return false; - } - return true; +// Parses a single file with filename filename. +void +Session::parse_file (const char *filename) +{ + RAIIFile file_wrap (filename); + + if (file_wrap.file == NULL) + { + fatal_error (UNKNOWN_LOCATION, "cannot open filename %s: %m", filename); } - /* Actual main entry point for front-end. Called from langhook to parse files. */ - void Session::parse_files(int num_files, const char** files) { - for (int i = 0; i < num_files; i++) { - parse_file(files[i]); - } - // TODO: should semantic analysis be dealed with here? or per file? for now, per-file. + // parse file here + // create lexer and parser - these are file-specific and so aren't instance + // variables + Rust::Lexer lex (filename, file_wrap.file, rust_get_linemap ()); + Rust::Parser parser (lex); + + // determine parsing method from options + /* FIXME: currently, the dump means that full compilation will not occur as of + * present. In future, dumps should not inhibit full compilation. */ + switch (options.dump_option) + { + case CompileOptions::NO_DUMP: + fatal_error (UNKNOWN_LOCATION, + "no-dump parsing has not been enabled yet"); + return; + case CompileOptions::LEXER_DUMP: + parser.debug_dump_lex_output (); + return; + case CompileOptions::PARSER_AST_DUMP: + parser.debug_dump_ast_output (); + return; + case CompileOptions::REGISTER_PLUGINS_DUMP: + case CompileOptions::INJECTION_DUMP: + case CompileOptions::EXPANSION_DUMP: + case CompileOptions::NAME_RESOLUTION_DUMP: + // will break later after more stages + break; + // semantic analysis when completed + default: + fatal_error (UNKNOWN_LOCATION, "unrecognised dump option: '%u'", + options.dump_option); + return; } - // Parses a single file with filename filename. - void Session::parse_file(const char* filename) { - RAIIFile file_wrap(filename); - - if (file_wrap.file == NULL) { - fatal_error(UNKNOWN_LOCATION, "cannot open filename %s: %m", filename); - } - - // parse file here - // create lexer and parser - these are file-specific and so aren't instance variables - Rust::Lexer lex(filename, file_wrap.file, rust_get_linemap()); - Rust::Parser parser(lex); - - // determine parsing method from options - /* FIXME: currently, the dump means that full compilation will not occur as of present. In - * future, dumps should not inhibit full compilation. */ - switch (options.dump_option) { - case CompileOptions::NO_DUMP: - fatal_error(UNKNOWN_LOCATION, "no-dump parsing has not been enabled yet"); - return; - case CompileOptions::LEXER_DUMP: - parser.debug_dump_lex_output(); - return; - case CompileOptions::PARSER_AST_DUMP: - parser.debug_dump_ast_output(); - return; - case CompileOptions::REGISTER_PLUGINS_DUMP: - case CompileOptions::INJECTION_DUMP: - case CompileOptions::EXPANSION_DUMP: - case CompileOptions::NAME_RESOLUTION_DUMP: - // will break later after more stages - break; - // semantic analysis when completed - default: - fatal_error(UNKNOWN_LOCATION, "unrecognised dump option: '%u'", options.dump_option); - return; - } - - /* basic pipeline: - * - lex - * - parse - * - register plugins (dummy stage for now) - attribute injection? what is this? - * (attribute injection is injecting attributes specified in command line into crate root) - * - injection (some lint checks or dummy, register builtin macros, crate injection) - * - expansion (expands all macros, maybe build test harness, AST validation, maybe macro - * crate) - * - name resolution (name resolution, maybe feature checking, maybe buffered lints) - * TODO not done */ - - // generate crate from parser - AST::Crate parsed_crate = parser.parse_crate(); - - fprintf(stderr, "\033[0;31mSUCCESSFULLY PARSED CRATE \n\033[0m"); - - // register plugins pipeline stage - register_plugins(parsed_crate); - fprintf(stderr, "\033[0;31mSUCCESSFULLY REGISTERED PLUGINS \n\033[0m"); - - if (options.dump_option == CompileOptions::REGISTER_PLUGINS_DUMP) { - // TODO: what do I dump here? - return; - } - - // injection pipeline stage - injection(parsed_crate); - fprintf(stderr, "\033[0;31mSUCCESSFULLY FINISHED INJECTION \n\033[0m"); - - if (options.dump_option == CompileOptions::INJECTION_DUMP) { - // TODO: what do I dump here? injected crate names? - return; - } - - // expansion pipeline stage - expansion(parsed_crate); - fprintf(stderr, "\033[0;31mSUCCESSFULLY FINISHED EXPANSION \n\033[0m"); - - if (options.dump_option == CompileOptions::EXPANSION_DUMP) { - // TODO: what do I dump here? expanded macros? AST with expanded macros? - return; - } - - // name resolution pipeline stage - name_resolution(parsed_crate); - fprintf(stderr, "\033[0;31mSUCCESSFULLY FINISHED NAME RESOLUTION \n\033[0m"); - - if (options.dump_option == CompileOptions::NAME_RESOLUTION_DUMP) { - // TODO: what do I dump here? resolved names? AST with resolved names? - return; - } + /* basic pipeline: + * - lex + * - parse + * - register plugins (dummy stage for now) - attribute injection? what is + * this? (attribute injection is injecting attributes specified in command + * line into crate root) + * - injection (some lint checks or dummy, register builtin macros, crate + * injection) + * - expansion (expands all macros, maybe build test harness, AST validation, + * maybe macro crate) + * - name resolution (name resolution, maybe feature checking, maybe buffered + * lints) + * TODO not done */ + + // generate crate from parser + AST::Crate parsed_crate = parser.parse_crate (); + + fprintf (stderr, "\033[0;31mSUCCESSFULLY PARSED CRATE \n\033[0m"); + + // register plugins pipeline stage + register_plugins (parsed_crate); + fprintf (stderr, "\033[0;31mSUCCESSFULLY REGISTERED PLUGINS \n\033[0m"); + + if (options.dump_option == CompileOptions::REGISTER_PLUGINS_DUMP) + { + // TODO: what do I dump here? + return; } - // Checks whether 'cfg' attribute prevents compilation. - bool check_cfg(const AST::Attribute& attr ATTRIBUTE_UNUSED) { - // if "has sub items", and if 'cfg' attr, recursively call this on sub items? + // injection pipeline stage + injection (parsed_crate); + fprintf (stderr, "\033[0;31mSUCCESSFULLY FINISHED INJECTION \n\033[0m"); + + if (options.dump_option == CompileOptions::INJECTION_DUMP) + { + // TODO: what do I dump here? injected crate names? + return; + } - // TODO: actually implement. assume true for now + // expansion pipeline stage + expansion (parsed_crate); + fprintf (stderr, "\033[0;31mSUCCESSFULLY FINISHED EXPANSION \n\033[0m"); - return true; + if (options.dump_option == CompileOptions::EXPANSION_DUMP) + { + // TODO: what do I dump here? expanded macros? AST with expanded macros? + return; } - // TODO: deprecated - don't use - // Checks whether any 'cfg' attribute on the item prevents compilation of that item. - bool check_item_cfg(::std::vector<AST::Attribute> attrs) { - for (const auto& attr : attrs) { - if (attr.get_path() == "cfg" && !check_cfg(attr)) { - return false; - } - } + // name resolution pipeline stage + name_resolution (parsed_crate); + fprintf (stderr, "\033[0;31mSUCCESSFULLY FINISHED NAME RESOLUTION \n\033[0m"); - return true; + if (options.dump_option == CompileOptions::NAME_RESOLUTION_DUMP) + { + // TODO: what do I dump here? resolved names? AST with resolved names? + return; } - // TODO: deprecated - don't use - - // TODO: actually implement method - void load_extern_crate(::std::string crate_name ATTRIBUTE_UNUSED) {} - // TODO: deprecated - don't use - - // Parses up to the "load (external) crates" part of the frontend. - // TODO: lots of this code is probably actually useful outside of dumping, so maybe split off - // function - void Session::debug_dump_load_crates(Parser& parser) { - // parse crate as AST - AST::Crate crate = parser.parse_crate(); - - /* TODO: search through inner attrs and see whether any of those attr paths contain "no_core", - * "no_std", "compiler_builtins". If so/not, save certain crate names. In these names, insert - * items at beginning of crate items. This is crate injection. Also, inject prelude use decl - * at beginning (first name is assumed to be prelude - prelude is a use decl automatically - * generated to enable using Option and Copy without qualifying it or importing it via 'use' - * manually) */ - - ::std::vector< ::std::string> crate_names; - for (const auto& item : crate.items) { - // if item is extern crate, add name? to list of stuff ONLY IF config is checked - // if item is module, iterate this loop inside it as well (recursive?) ONLY IF config is - // checked - - // TODO: actually do the checks somewhere - probably in the items - - item->add_crate_name(crate_names); - } - - /* loop through list of crate names/paths/whatever, attempting to load each one. save loaded - * crates to a Session variable? Or save to current AST::Crate? */ - for (const auto& name : crate_names) { - load_extern_crate(name /*, basename = ""?*/); - } - // for each loaded crate, load dependencies of it as well +} + +// Checks whether 'cfg' attribute prevents compilation. +bool +check_cfg (const AST::Attribute &attr ATTRIBUTE_UNUSED) +{ + // if "has sub items", and if 'cfg' attr, recursively call this on sub items? + + // TODO: actually implement. assume true for now + + return true; +} +// TODO: deprecated - don't use + +// Checks whether any 'cfg' attribute on the item prevents compilation of that +// item. +bool +check_item_cfg (::std::vector<AST::Attribute> attrs) +{ + for (const auto &attr : attrs) + { + if (attr.get_path () == "cfg" && !check_cfg (attr)) + { + return false; + } + } + + return true; +} +// TODO: deprecated - don't use + +// TODO: actually implement method +void +load_extern_crate (::std::string crate_name ATTRIBUTE_UNUSED) +{} +// TODO: deprecated - don't use + +// Parses up to the "load (external) crates" part of the frontend. +// TODO: lots of this code is probably actually useful outside of dumping, so +// maybe split off function +void +Session::debug_dump_load_crates (Parser &parser) +{ + // parse crate as AST + AST::Crate crate = parser.parse_crate (); + + /* TODO: search through inner attrs and see whether any of those attr paths + * contain "no_core", "no_std", "compiler_builtins". If so/not, save certain + * crate names. In these names, insert items at beginning of crate items. This + * is crate injection. Also, inject prelude use decl at beginning (first name + * is assumed to be prelude - prelude is a use decl automatically generated to + * enable using Option and Copy without qualifying it or importing it via + * 'use' manually) */ + + ::std::vector< ::std::string> crate_names; + for (const auto &item : crate.items) + { + // if item is extern crate, add name? to list of stuff ONLY IF config is + // checked if item is module, iterate this loop inside it as well + // (recursive?) ONLY IF config is checked + + // TODO: actually do the checks somewhere - probably in the items + + item->add_crate_name (crate_names); + } + + /* loop through list of crate names/paths/whatever, attempting to load each + * one. save loaded crates to a Session variable? Or save to current + * AST::Crate? */ + for (const auto &name : crate_names) + { + load_extern_crate (name /*, basename = ""?*/); + } + // for each loaded crate, load dependencies of it as well +} +// TODO: deprecated - don't use + +void +Session::register_plugins (AST::Crate &crate ATTRIBUTE_UNUSED) +{ + fprintf (stderr, "ran register_plugins (with no body)\n"); +} + +// TODO: move somewhere else +bool +contains_name (::std::vector<AST::Attribute> attrs, ::std::string name) +{ + for (const auto &attr : attrs) + { + if (attr.get_path () == name) + { + return true; + } } - // TODO: deprecated - don't use - void Session::register_plugins(AST::Crate& crate ATTRIBUTE_UNUSED) { - fprintf(stderr, "ran register_plugins (with no body)\n"); + return false; +} + +void +Session::injection (AST::Crate &crate) +{ + fprintf (stderr, "started injection\n"); + + // lint checks in future maybe? + + // register builtin macros + /* In rustc, builtin macros are divided into 3 categories depending on use - + * "bang" macros, "attr" macros, and "derive" macros. I think the meanings of + * these categories should be fairly obvious to anyone who has used rust. + * Builtin macro list by category: Bang + * - asm + * - assert + * - cfg + * - column + * - compile_error + * - concat_idents + * - concat + * - env + * - file + * - format_args_nl + * - format_args + * - global_asm + * - include_bytes + * - include_str + * - include + * - line + * - log_syntax + * - module_path + * - option_env + * - stringify + * - trace_macros + * Attr + * - bench + * - global_allocator + * - test + * - test_case + * Derive + * - Clone + * - Copy + * - Debug + * - Default + * - Eq + * - Hash + * - Ord + * - PartialEq + * - PartialOrd + * - RustcDecodable + * - RustcEncodable + * rustc also has a "quote" macro that is defined differently and is + * supposedly not stable so eh. */ + /* TODO: actually implement injection of these macros. In particular, derive + * macros, cfg, and + * test should be prioritised since they seem to be used the most. */ + + // crate injection + ::std::vector< ::std::string> names; + if (contains_name (crate.inner_attrs, "no_core")) + { + // no prelude + injected_crate_name = ""; } + else if (contains_name (crate.inner_attrs, "no_std")) + { + names.push_back ("core"); - // TODO: move somewhere else - bool contains_name(const std::vector<AST::Attribute>& attrs, std::string name) { - for (const auto& attr : attrs) { - if (attr.get_path() == name) { - return true; - } - } + if (!contains_name (crate.inner_attrs, "compiler_builtins")) + { + names.push_back ("compiler_builtins"); + } - return false; + injected_crate_name = "core"; } + else + { + names.push_back ("std"); - void Session::injection(AST::Crate& crate) { - fprintf(stderr, "started injection\n"); - - // lint checks in future maybe? - - // register builtin macros - /* In rustc, builtin macros are divided into 3 categories depending on use - "bang" macros, - * "attr" macros, and "derive" macros. I think the meanings of these categories should be - * fairly obvious to anyone who has used rust. Builtin macro list by category: Bang - * - asm - * - assert - * - cfg - * - column - * - compile_error - * - concat_idents - * - concat - * - env - * - file - * - format_args_nl - * - format_args - * - global_asm - * - include_bytes - * - include_str - * - include - * - line - * - log_syntax - * - module_path - * - option_env - * - stringify - * - trace_macros - * Attr - * - bench - * - global_allocator - * - test - * - test_case - * Derive - * - Clone - * - Copy - * - Debug - * - Default - * - Eq - * - Hash - * - Ord - * - PartialEq - * - PartialOrd - * - RustcDecodable - * - RustcEncodable - * rustc also has a "quote" macro that is defined differently and is supposedly not stable so - * eh. */ - /* TODO: actually implement injection of these macros. In particular, derive macros, cfg, and - * test should be prioritised since they seem to be used the most. */ - - // crate injection - ::std::vector< ::std::string> names; - if (contains_name(crate.inner_attrs, "no_core")) { - // no prelude - injected_crate_name = ""; - } else if (contains_name(crate.inner_attrs, "no_std")) { - names.push_back("core"); - - if (!contains_name(crate.inner_attrs, "compiler_builtins")) { - names.push_back("compiler_builtins"); - } - - injected_crate_name = "core"; - } else { - names.push_back("std"); - - injected_crate_name = "std"; - } - - // reverse iterate through names to insert crate items in "forward" order at beginning of - // crate - for (auto it = names.rbegin(); it != names.rend(); ++it) { - // create "macro use" attribute for use on extern crate item to enable loading macros from - // it - AST::Attribute attr(AST::SimplePath::from_str("macro_use"), NULL); - - // create "extern crate" item with the name - ::std::unique_ptr<AST::ExternCrate> extern_crate( - new AST::ExternCrate(*it, AST::Visibility::create_error(), { ::std::move(attr) }, - Linemap::unknown_location())); - - // insert at beginning - crate.items.insert(crate.items.begin(), ::std::move(extern_crate)); - } - - // create use tree path - // prelude is injected_crate_name - ::std::vector<AST::SimplePathSegment> segments - = { AST::SimplePathSegment(injected_crate_name), AST::SimplePathSegment("prelude"), - AST::SimplePathSegment("v1") }; - // create use tree and decl - ::std::unique_ptr<AST::UseTreeGlob> use_tree(new AST::UseTreeGlob( - AST::UseTreeGlob::PATH_PREFIXED, AST::SimplePath(::std::move(segments)), Location())); - AST::Attribute prelude_attr(AST::SimplePath::from_str("prelude_import"), NULL); - ::std::unique_ptr<AST::UseDeclaration> use_decl(new AST::UseDeclaration(::std::move(use_tree), - AST::Visibility::create_error(), { ::std::move(prelude_attr) }, Location())); - - crate.items.insert(crate.items.begin(), ::std::move(use_decl)); - - /* TODO: potentially add checking attribute crate type? I can't figure out what this does - * currently comment says "Unconditionally collect crate types from attributes to make them - * used", which presumably refers to checking the linkage info by "crate_type". It also seems - * to ensure that an invalid crate type is not specified, so maybe just do that. Valid crate - * types: bin lib dylib staticlib cdylib rlib proc-macro */ - - fprintf(stderr, "finished injection\n"); + injected_crate_name = "std"; } - void Session::expansion(AST::Crate& crate ATTRIBUTE_UNUSED) { - fprintf(stderr, "started expansion\n"); + // reverse iterate through names to insert crate items in "forward" order + // at beginning of crate + for (auto it = names.rbegin (); it != names.rend (); ++it) + { + // create "macro use" attribute for use on extern crate item to enable + // loading macros from it + AST::Attribute attr (AST::SimplePath::from_str ("macro_use"), NULL); + + // create "extern crate" item with the name + ::std::unique_ptr<AST::ExternCrate> extern_crate ( + new AST::ExternCrate (*it, AST::Visibility::create_error (), + {::std::move (attr)}, + Linemap::unknown_location ())); + + // insert at beginning + crate.items.insert (crate.items.begin (), ::std::move (extern_crate)); + } - // rustc has a modification to windows PATH temporarily here, which may end up being required + // create use tree path + // prelude is injected_crate_name + ::std::vector<AST::SimplePathSegment> segments + = {AST::SimplePathSegment (injected_crate_name), + AST::SimplePathSegment ("prelude"), AST::SimplePathSegment ("v1")}; + // create use tree and decl + ::std::unique_ptr<AST::UseTreeGlob> use_tree ( + new AST::UseTreeGlob (AST::UseTreeGlob::PATH_PREFIXED, + AST::SimplePath (::std::move (segments)), + Location ())); + AST::Attribute prelude_attr (AST::SimplePath::from_str ("prelude_import"), + NULL); + ::std::unique_ptr<AST::UseDeclaration> use_decl ( + new AST::UseDeclaration (::std::move (use_tree), + AST::Visibility::create_error (), + {::std::move (prelude_attr)}, Location ())); + + crate.items.insert (crate.items.begin (), ::std::move (use_decl)); + + /* TODO: potentially add checking attribute crate type? I can't figure out + * what this does currently comment says "Unconditionally collect crate + * types from attributes to make them used", which presumably refers to + * checking the linkage info by "crate_type". It also seems to ensure that + * an invalid crate type is not specified, so maybe just do that. Valid + * crate types: bin lib dylib staticlib cdylib rlib proc-macro */ + + fprintf (stderr, "finished injection\n"); +} - // create macro expansion config? - // if not, would at least have to configure recursion_limit +void +Session::expansion (AST::Crate &crate ATTRIBUTE_UNUSED) +{ + fprintf (stderr, "started expansion\n"); - // create extctxt? from parse session, cfg, and resolver? - // expand by calling cxtctxt object's monotonic_expander's expand_crate method. + // rustc has a modification to windows PATH temporarily here, which may end + // up being required - // error reporting - check unused macros, get missing fragment specifiers + // create macro expansion config? + // if not, would at least have to configure recursion_limit - // build test harness + // create extctxt? from parse session, cfg, and resolver? + // expand by calling cxtctxt object's monotonic_expander's expand_crate + // method. - // ast validation (also with proc macro decls) + // error reporting - check unused macros, get missing fragment specifiers - // maybe create macro crate if not rustdoc + // build test harness - fprintf(stderr, "finished expansion\n"); - } + // ast validation (also with proc macro decls) - void Session::name_resolution(AST::Crate& crate ATTRIBUTE_UNUSED) { - fprintf(stderr, "started name resolution\n"); + // maybe create macro crate if not rustdoc - fprintf(stderr, "finished name resolution\n"); - } + fprintf (stderr, "finished expansion\n"); +} - // NOTEs: - /* mrustc compile pipeline: - * - target load (pass target spec to parser?) - * - parse (convert source to AST) - * - load crates (load any explicitly mentioned extern crates [not all of them]) - * - expand (AST transformations from attributes and macros, loads remaining extern crates - * [std/core and any triggered by macro expansion]) - * - implicit crates (test harness, allocator crate, panic crate) - * - resolve use (annotate every 'use' item with source [supposedly handles nasty recursion]) - * - resolve index (generate index of visible items for every module [avoids recursion in next - * pass]) - * - resolve absolute (resolve all paths into either variable names [types/values] or absolute - * paths) - * - HIR lower (convert modified AST to simpler HIR [both expressions and module tree]) - * - resolve type aliases (replace any usages of type aliases with actual type [except associated - * types]) - * - resolve bind (iterate HIR tree and set binding annotations on all concrete types [avoids - * path lookups later]) - * - resolve HIR markings (generate "markings" [e.g. for Copy/Send/Sync/...] for all types - * - sort impls (small pass - sort impls into groups) - * - resolve UFCS outer (determine source trait for all top-level <T>::Type [qualified] paths) - * - resolve UFCS paths (do the same, but include for exprs this time. also normalises results of - * previous pass [expanding known associated types]) - * - constant evaluate (evaluate all constants) - * - typecheck outer (checks impls are sane) - * - typecheck expressions (resolve and check types for all exprs) - * - expand HIR annotate (annotate how exprs are used - used for closure extractions and - * reborrows) - * - expand HIR closures (extract closures into structs implementing Fn* traits) - * - expand HIR vtables (generate vtables for types with dyn dispatch) - * - expand HIR calls (converts method and callable calls into explicit function calls) - * - expand HIR reborrows (apply reborrow rules [taking '&mut *v' instead of 'v']) - * - expand HIR erasedtype (replace all erased types 'impl Trait' with the true type) - * - typecheck expressions (validate - double check that previous passes haven't broke type - * system rules) - * - lower MIR (convert HIR exprs into a control-flow graph [MIR]) - * - MIR validate (check that the generated MIR is consistent) - * - MIR cleanup (perform various transformations on MIR - replace reads of const items with the - * item itself; convert casts to unsized types into 'MakeDst' operations) - * - MIR optimise (perform various simple optimisations on the MIR - constant propagation, dead - * code elimination, borrow elimination, some inlining) - * - MIR validate PO (re-validate the MIR) - * - MIR validate full (optionally: perform expensive state-tracking validation on MIR) - * - trans enumerate (enumerate all items needed for code generation, primarily types used for - * generics) - * - trans auto impls (create magic trait impls as enumerated in previous pass) - * - trans monomorph (generate monomorphised copies of all functions [with generics replaced with - * real types]) - * - MIR optimise inline (run optimisation again, this time with full type info [primarily for - * inlining]) - * - HIR serialise (write out HIR dump [module tree and generic/inline MIR]) - * - trans codegen (generate final output file: emit C source file and call C compiler) */ - - /* rustc compile pipeline (basic, in way less detail): - * - parse input (parse .rs to AST) - * - name resolution, macro expansion, and configuration (process AST recursively, resolving - * paths, expanding macros, processing #[cfg] nodes [i.e. maybe stripping stuff from AST]) - * - lower to HIR - * - type check and other analyses (e.g. privacy checking) - * - lower to MIR and post-processing (and do stuff like borrow checking) - * - translation to LLVM IR and LLVM optimisations (produce the .o files) - * - linking (link together .o files) */ - - /* Pierced-together rustc compile pipeline (from source): - * - parse input (parse file to crate) - * - register plugins (attributes injection, set various options, register lints, load plugins) - * - expansion/configure and expand (initial 'cfg' processing, 'loading compiler plugins', - * syntax expansion, secondary 'cfg' expansion, synthesis of a test harness if required, - * injection of any std lib dependency and prelude, and name resolution) - actually documented - * inline - * - seeming pierced-together order: pre-AST expansion lint checks, registering builtin - * macros, crate injection, then expand all macros, then maybe build test harness, AST validation, - * maybe create a macro crate (if not rustdoc), name resolution, complete gated feature - * checking, add all buffered lints - * - create global context (lower to HIR) - * - analysis on global context (HIR optimisations? create MIR?) - * - code generation - * - link */ +void +Session::name_resolution (AST::Crate &crate ATTRIBUTE_UNUSED) +{ + fprintf (stderr, "started name resolution\n"); + + fprintf (stderr, "finished name resolution\n"); } + +// NOTEs: +/* mrustc compile pipeline: + * - target load (pass target spec to parser?) + * - parse (convert source to AST) + * - load crates (load any explicitly mentioned extern crates [not all of + * them]) + * - expand (AST transformations from attributes and macros, loads remaining + * extern crates [std/core and any triggered by macro expansion]) + * - implicit crates (test harness, allocator crate, panic crate) + * - resolve use (annotate every 'use' item with source [supposedly handles + * nasty recursion]) + * - resolve index (generate index of visible items for every module [avoids + * recursion in next pass]) + * - resolve absolute (resolve all paths into either variable names + * [types/values] or absolute paths) + * - HIR lower (convert modified AST to simpler HIR [both expressions and + * module tree]) + * - resolve type aliases (replace any usages of type aliases with actual + * type [except associated types]) + * - resolve bind (iterate HIR tree and set binding annotations on all + * concrete types [avoids path lookups later]) + * - resolve HIR markings (generate "markings" [e.g. for Copy/Send/Sync/...] + * for all types + * - sort impls (small pass - sort impls into groups) + * - resolve UFCS outer (determine source trait for all top-level <T>::Type + * [qualified] paths) + * - resolve UFCS paths (do the same, but include for exprs this time. also + * normalises results of previous pass [expanding known associated types]) + * - constant evaluate (evaluate all constants) + * - typecheck outer (checks impls are sane) + * - typecheck expressions (resolve and check types for all exprs) + * - expand HIR annotate (annotate how exprs are used - used for closure + * extractions and reborrows) + * - expand HIR closures (extract closures into structs implementing Fn* + * traits) + * - expand HIR vtables (generate vtables for types with dyn dispatch) + * - expand HIR calls (converts method and callable calls into explicit + * function calls) + * - expand HIR reborrows (apply reborrow rules [taking '&mut *v' instead of + * 'v']) + * - expand HIR erasedtype (replace all erased types 'impl Trait' with the + * true type) + * - typecheck expressions (validate - double check that previous passes + * haven't broke type system rules) + * - lower MIR (convert HIR exprs into a control-flow graph [MIR]) + * - MIR validate (check that the generated MIR is consistent) + * - MIR cleanup (perform various transformations on MIR - replace reads of + * const items with the item itself; convert casts to unsized types into + * 'MakeDst' operations) + * - MIR optimise (perform various simple optimisations on the MIR - constant + * propagation, dead code elimination, borrow elimination, some inlining) + * - MIR validate PO (re-validate the MIR) + * - MIR validate full (optionally: perform expensive state-tracking + * validation on MIR) + * - trans enumerate (enumerate all items needed for code generation, + * primarily types used for generics) + * - trans auto impls (create magic trait impls as enumerated in previous + * pass) + * - trans monomorph (generate monomorphised copies of all functions [with + * generics replaced with real types]) + * - MIR optimise inline (run optimisation again, this time with full type + * info [primarily for inlining]) + * - HIR serialise (write out HIR dump [module tree and generic/inline MIR]) + * - trans codegen (generate final output file: emit C source file and call C + * compiler) */ + +/* rustc compile pipeline (basic, in way less detail): + * - parse input (parse .rs to AST) + * - name resolution, macro expansion, and configuration (process AST + * recursively, resolving paths, expanding macros, processing #[cfg] nodes + * [i.e. maybe stripping stuff from AST]) + * - lower to HIR + * - type check and other analyses (e.g. privacy checking) + * - lower to MIR and post-processing (and do stuff like borrow checking) + * - translation to LLVM IR and LLVM optimisations (produce the .o files) + * - linking (link together .o files) */ + +/* Pierced-together rustc compile pipeline (from source): + * - parse input (parse file to crate) + * - register plugins (attributes injection, set various options, register + * lints, load plugins) + * - expansion/configure and expand (initial 'cfg' processing, 'loading + * compiler plugins', syntax expansion, secondary 'cfg' expansion, synthesis + * of a test harness if required, injection of any std lib dependency and + * prelude, and name resolution) - actually documented inline + * - seeming pierced-together order: pre-AST expansion lint checks, + * registering builtin macros, crate injection, then expand all macros, then + * maybe build test harness, AST validation, maybe create a macro crate (if + * not rustdoc), name resolution, complete gated feature checking, add all + * buffered lints + * - create global context (lower to HIR) + * - analysis on global context (HIR optimisations? create MIR?) + * - code generation + * - link */ +} // namespace Rust diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index 84b5546..1ce3a92 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -18,174 +18,206 @@ #include <utility> namespace Rust { - // parser forward decl - class Parser; - // crate forward decl - namespace AST { - struct Crate; - } - - // Data related to target, most useful for conditional compilation and whatever. - struct TargetOptions { - // TODO: maybe make private and access through helpers to allow changes to impl - std::unordered_map<std::string, std::unordered_set<std::string>> features; - - public: - // Returns whether a key is defined in the feature set. - bool has_key(std::string key) const { - return features.find(key) != features.end(); - } - - // Returns whether a key exists with the given value in the feature set. - bool has_key_value_pair(std::string key, std::string value) const { - auto it = features.find(key); - if (it != features.end()) { - auto set = it->second; - auto it2 = set.find(value); - if (it2 != set.end()) - return true; - } - return false; - } - - // Returns the singular value from the key, or if the key has multiple, an empty string. - std::string get_singular_value(std::string key) const { - auto it = features.find(key); - if (it != features.end()) { - auto set = it->second; - if (set.size() == 1) - return *set.begin(); - } - return ""; - } - - // Returns all values associated with a key (including none), or an empty set if no key is found. - std::unordered_set< ::std::string> get_values_for_key(std::string key) const { - auto it = features.find(key); - if (it != features.end()) { - return it->second; - } - return {}; - } - - /* Inserts a key (no value) into the feature set. This will do nothing if the key already exists. - * This returns whether the insertion was successful (i.e. whether key already existed). */ - bool insert_key(std::string key) { - return features.insert(std::make_pair(key, std::unordered_set<std::string>())).second; - } - - // Inserts a key-value pair into the feature set. - void insert_key_value_pair(std::string key, std::string value) { - auto existing_set = get_values_for_key(key); - existing_set.insert(std::move(value)); - features[std::move(key)] = std::move(existing_set); - } - - /* According to reference, Rust uses either multi-map key-values or just values (although - * values may be aliases for a key-value value). This seems like overkill. Thus, depending on - * whether the attributes used in cfg are fixed or not, I think I'll either put each - * non-multimap "key-value" as a separate field and have the multimap "key-values" in a - * regular map for that one key, or actually use a multimap. - * - * rustc itself uses a set of key-value tuples where the second tuple element is optional. - * This gets rid of the requirement to make a multi-map, I guess, but seems like it might make - * search slow (unless all "is defined"-only ones have empty string as second element). */ - /* cfg attributes: - * - target_arch: single value - * - target_feature: multiple values possible - * - target_os: single value - * - target_family: single value (or no value?) - * - unix: set when target_family = "unix" - * - windows: set when target_family = "windows" - * - if these are just syntactic sugar, then maybe have a separate set or map for this kind - * of stuff - * - target_env: set when needed for disambiguation about ABI - usually empty string for GNU, - * complicated - * - seems to be a single value (if any) - * - target_endian: single value; "little" or "big" - * - target_pointer_width: single value, "32" for 32-bit pointers, etc. - * - target_vendor, single value - * - test: set when testing is being done - * - again, seems similar to a "is defined" rather than "is equal to" like unix - * - debug_assertions: seems to "is defined" - * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is defined" */ - }; - - // Defines compiler options (e.g. dump, etc.). - struct CompileOptions { - // TODO: use bitfield for smaller memory requirements? - - // FIXME: this is set up for "instead of" dumping - in future, dumps should not inhibit - // compilation - enum DumpOptions { - NO_DUMP, - LEXER_DUMP, - PARSER_AST_DUMP, - REGISTER_PLUGINS_DUMP, - INJECTION_DUMP, - EXPANSION_DUMP, - NAME_RESOLUTION_DUMP, - // TODO: add more? - } dump_option; - - // configuration options - actually useful for conditional compilation and whatever - // data related to target arch, features, os, family, env, endian, pointer width, vendor - TargetOptions target_data; - bool enable_test = false; - bool debug_assertions = false; - bool proc_macro = false; - }; - - /* Defines a compiler session. This is for a single compiler invocation, so potentially includes - * parsing multiple crates. */ - struct Session { - CompileOptions options; - // This should really be in a per-crate storage area but it is wiped with every file so eh. - ::std::string injected_crate_name; - - // backend wrapper to GCC GENERIC - Backend* backend; - - // backend linemap - Linemap* linemap; - - // TODO: replace raw pointers with smart pointers? - - public: - /* Initialise compiler session. Corresponds to langhook grs_langhook_init(). Note that this is - * called after option handling. */ - void init(); - bool handle_option(enum opt_code code, const char* arg, HOST_WIDE_INT value, int kind, - location_t loc, const struct cl_option_handlers* handlers); - void parse_files(int num_files, const char** files); - void init_options(); - - private: - // TODO: should this be private or public? - void parse_file(const char* filename); - bool enable_dump(::std::string arg); - - void debug_dump_load_crates(Parser& parser); - - void implicitly_enable_feature(::std::string feature_name); - void enable_features(); - - // pipeline stages - TODO maybe move? - /* Register plugins pipeline stage. TODO maybe move to another object? Currently dummy stage. - * In future will handle attribute injection (top-level inner attribute creation from command - * line arguments), setting options maybe, registering lints maybe, loading plugins maybe. */ - void register_plugins(AST::Crate& crate); - /* Injection pipeline stage. TODO maybe move to another object? Maybe have some lint checks - * (in future, obviously), register builtin macros, crate injection. */ - void injection(AST::Crate& crate); - /* Expansion pipeline stage. TODO maybe move to another object? Expands all macros, maybe - * build test harness in future, AST validation, maybe create macro crate (if not rustdoc).*/ - void expansion(AST::Crate& crate); - /* Name resolution pipeline stage. TODO maybe move to another object. Performs name - * resolution, maybe complete gated feature checking, maybe create buffered lints in future. - */ - void name_resolution(AST::Crate& crate); - }; +// parser forward decl +class Parser; +// crate forward decl +namespace AST { +struct Crate; } +// Data related to target, most useful for conditional compilation and whatever. +struct TargetOptions +{ + // TODO: maybe make private and access through helpers to allow changes to + // impl + std::unordered_map<std::string, std::unordered_set<std::string> > features; + +public: + // Returns whether a key is defined in the feature set. + bool has_key (std::string key) const + { + return features.find (key) != features.end (); + } + + // Returns whether a key exists with the given value in the feature set. + bool has_key_value_pair (std::string key, std::string value) const + { + auto it = features.find (key); + if (it != features.end ()) + { + auto set = it->second; + auto it2 = set.find (value); + if (it2 != set.end ()) + return true; + } + return false; + } + + // Returns the singular value from the key, or if the key has multiple, an + // empty string. + std::string get_singular_value (std::string key) const + { + auto it = features.find (key); + if (it != features.end ()) + { + auto set = it->second; + if (set.size () == 1) + return *set.begin (); + } + return ""; + } + + // Returns all values associated with a key (including none), or an empty set + // if no key is found. + std::unordered_set< ::std::string> get_values_for_key (std::string key) const + { + auto it = features.find (key); + if (it != features.end ()) + { + return it->second; + } + return {}; + } + + /* Inserts a key (no value) into the feature set. This will do nothing if the + * key already exists. + * This returns whether the insertion was successful (i.e. whether key already + * existed). */ + bool insert_key (std::string key) + { + return features + .insert (std::make_pair (key, std::unordered_set<std::string> ())) + .second; + } + + // Inserts a key-value pair into the feature set. + void insert_key_value_pair (std::string key, std::string value) + { + auto existing_set = get_values_for_key (key); + existing_set.insert (std::move (value)); + features[std::move (key)] = std::move (existing_set); + } + + /* According to reference, Rust uses either multi-map key-values or just + * values (although values may be aliases for a key-value value). This seems + * like overkill. Thus, depending on whether the attributes used in cfg are + * fixed or not, I think I'll either put each non-multimap "key-value" as a + * separate field and have the multimap "key-values" in a regular map for that + * one key, or actually use a multimap. + * + * rustc itself uses a set of key-value tuples where the second tuple element + * is optional. This gets rid of the requirement to make a multi-map, I guess, + * but seems like it might make + * search slow (unless all "is defined"-only ones have empty string as second + * element). */ + /* cfg attributes: + * - target_arch: single value + * - target_feature: multiple values possible + * - target_os: single value + * - target_family: single value (or no value?) + * - unix: set when target_family = "unix" + * - windows: set when target_family = "windows" + * - if these are just syntactic sugar, then maybe have a separate set or map + * for this kind of stuff + * - target_env: set when needed for disambiguation about ABI - usually empty + * string for GNU, complicated + * - seems to be a single value (if any) + * - target_endian: single value; "little" or "big" + * - target_pointer_width: single value, "32" for 32-bit pointers, etc. + * - target_vendor, single value + * - test: set when testing is being done + * - again, seems similar to a "is defined" rather than "is equal to" like + * unix + * - debug_assertions: seems to "is defined" + * - proc_macro: no idea, bad docs. seems to be boolean, so maybe "is defined" + */ +}; + +// Defines compiler options (e.g. dump, etc.). +struct CompileOptions +{ + // TODO: use bitfield for smaller memory requirements? + + // FIXME: this is set up for "instead of" dumping - in future, dumps should + // not inhibit compilation + enum DumpOptions + { + NO_DUMP, + LEXER_DUMP, + PARSER_AST_DUMP, + REGISTER_PLUGINS_DUMP, + INJECTION_DUMP, + EXPANSION_DUMP, + NAME_RESOLUTION_DUMP, + // TODO: add more? + } dump_option; + + // configuration options - actually useful for conditional compilation and + // whatever data related to target arch, features, os, family, env, endian, + // pointer width, vendor + TargetOptions target_data; + bool enable_test = false; + bool debug_assertions = false; + bool proc_macro = false; +}; + +/* Defines a compiler session. This is for a single compiler invocation, so + * potentially includes parsing multiple crates. */ +struct Session +{ + CompileOptions options; + // This should really be in a per-crate storage area but it is wiped with + // every file so eh. + ::std::string injected_crate_name; + + // backend wrapper to GCC GENERIC + Backend *backend; + + // backend linemap + Linemap *linemap; + + // TODO: replace raw pointers with smart pointers? + +public: + /* Initialise compiler session. Corresponds to langhook grs_langhook_init(). + * Note that this is called after option handling. */ + void init (); + bool handle_option (enum opt_code code, const char *arg, HOST_WIDE_INT value, + int kind, location_t loc, + const struct cl_option_handlers *handlers); + void parse_files (int num_files, const char **files); + void init_options (); + +private: + // TODO: should this be private or public? + void parse_file (const char *filename); + bool enable_dump (::std::string arg); + + void debug_dump_load_crates (Parser &parser); + + void implicitly_enable_feature (::std::string feature_name); + void enable_features (); + + // pipeline stages - TODO maybe move? + /* Register plugins pipeline stage. TODO maybe move to another object? + * Currently dummy stage. In future will handle attribute injection (top-level + * inner attribute creation from command line arguments), setting options + * maybe, registering lints maybe, loading plugins maybe. */ + void register_plugins (AST::Crate &crate); + /* Injection pipeline stage. TODO maybe move to another object? Maybe have + * some lint checks (in future, obviously), register builtin macros, crate + * injection. */ + void injection (AST::Crate &crate); + /* Expansion pipeline stage. TODO maybe move to another object? Expands all + * macros, maybe build test harness in future, AST validation, maybe create + * macro crate (if not rustdoc).*/ + void expansion (AST::Crate &crate); + /* Name resolution pipeline stage. TODO maybe move to another object. Performs + * name resolution, maybe complete gated feature checking, maybe create + * buffered lints in future. + */ + void name_resolution (AST::Crate &crate); +}; +} // namespace Rust + #endif diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h index 84e66aa..da2454a 100644 --- a/gcc/rust/rust-system.h +++ b/gcc/rust/rust-system.h @@ -1,5 +1,5 @@ // rust-system.h -- Rust frontend inclusion of gcc header files -*- C++ -*- -// Copyright (C) 2009-2019 Free Software Foundation, Inc. +// Copyright (C) 2009-2020 Free Software Foundation, Inc. // This file is part of GCC. @@ -41,94 +41,84 @@ #include <deque> #include <functional> -/* TODO: strictly speaking, as AST move semantics make frontend C++11-and-up only, unordered map should - * always be definable (i.e. don't have to resort to tr1 like in C++03), so don't need to have this - * macro switch - just include <unordered_map> and <unordered_set>. */ +/* TODO: strictly speaking, as AST move semantics make frontend C++11-and-up + * only, unordered map should always be definable (i.e. don't have to resort to + * tr1 like in C++03), so don't need to have this macro switch - just include + * <unordered_map> and <unordered_set>. */ #if defined(HAVE_UNORDERED_MAP) -# include <unordered_map> -# include <unordered_set> +#include <unordered_map> +#include <unordered_set> -# define Unordered_map(KEYTYPE, VALTYPE) \ - std::unordered_map<KEYTYPE, VALTYPE> +#define Unordered_map(KEYTYPE, VALTYPE) std::unordered_map<KEYTYPE, VALTYPE> -# define Unordered_map_hash(KEYTYPE, VALTYPE, HASHFN, EQFN) \ - std::unordered_map<KEYTYPE, VALTYPE, HASHFN, EQFN> +#define Unordered_map_hash(KEYTYPE, VALTYPE, HASHFN, EQFN) \ + std::unordered_map<KEYTYPE, VALTYPE, HASHFN, EQFN> -# define Unordered_set(KEYTYPE) \ - std::unordered_set<KEYTYPE> +#define Unordered_set(KEYTYPE) std::unordered_set<KEYTYPE> -# define Unordered_set_hash(KEYTYPE, HASHFN, EQFN) \ - std::unordered_set<KEYTYPE, HASHFN, EQFN> +#define Unordered_set_hash(KEYTYPE, HASHFN, EQFN) \ + std::unordered_set<KEYTYPE, HASHFN, EQFN> #elif defined(HAVE_TR1_UNORDERED_MAP) -# include <tr1/unordered_map> -# include <tr1/unordered_set> +#include <tr1/unordered_map> +#include <tr1/unordered_set> -# define Unordered_map(KEYTYPE, VALTYPE) \ - std::tr1::unordered_map<KEYTYPE, VALTYPE> +#define Unordered_map(KEYTYPE, VALTYPE) \ + std::tr1::unordered_map<KEYTYPE, VALTYPE> -# define Unordered_map_hash(KEYTYPE, VALTYPE, HASHFN, EQFN) \ - std::tr1::unordered_map<KEYTYPE, VALTYPE, HASHFN, EQFN> +#define Unordered_map_hash(KEYTYPE, VALTYPE, HASHFN, EQFN) \ + std::tr1::unordered_map<KEYTYPE, VALTYPE, HASHFN, EQFN> -# define Unordered_set(KEYTYPE) \ - std::tr1::unordered_set<KEYTYPE> +#define Unordered_set(KEYTYPE) std::tr1::unordered_set<KEYTYPE> -# define Unordered_set_hash(KEYTYPE, HASHFN, EQFN) \ - std::tr1::unordered_set<KEYTYPE, HASHFN, EQFN> +#define Unordered_set_hash(KEYTYPE, HASHFN, EQFN) \ + std::tr1::unordered_set<KEYTYPE, HASHFN, EQFN> #elif defined(HAVE_EXT_HASH_MAP) -# include <ext/hash_map> -# include <ext/hash_set> +#include <ext/hash_map> +#include <ext/hash_set> -# define Unordered_map(KEYTYPE, VALTYPE) \ - __gnu_cxx::hash_map<KEYTYPE, VALTYPE> +#define Unordered_map(KEYTYPE, VALTYPE) __gnu_cxx::hash_map<KEYTYPE, VALTYPE> -# define Unordered_map_hash(KEYTYPE, VALTYPE, HASHFN, EQFN) \ - __gnu_cxx::hash_map<KEYTYPE, VALTYPE, HASHFN, EQFN> +#define Unordered_map_hash(KEYTYPE, VALTYPE, HASHFN, EQFN) \ + __gnu_cxx::hash_map<KEYTYPE, VALTYPE, HASHFN, EQFN> -# define Unordered_set(KEYTYPE) \ - __gnu_cxx::hash_set<KEYTYPE> +#define Unordered_set(KEYTYPE) __gnu_cxx::hash_set<KEYTYPE> -# define Unordered_set_hash(KEYTYPE, HASHFN, EQFN) \ - __gnu_cxx::hash_set<KEYTYPE, HASHFN, EQFN> +#define Unordered_set_hash(KEYTYPE, HASHFN, EQFN) \ + __gnu_cxx::hash_set<KEYTYPE, HASHFN, EQFN> // Provide hash functions for strings and pointers. -namespace __gnu_cxx -{ +namespace __gnu_cxx { -template<> -struct hash<std::string> +template <> struct hash<std::string> { - size_t - operator()(std::string s) const - { return __stl_hash_string(s.c_str()); } + size_t operator() (std::string s) const + { + return __stl_hash_string (s.c_str ()); + } }; -template<typename T> -struct hash<T*> +template <typename T> struct hash<T *> { - size_t - operator()(T* p) const - { return reinterpret_cast<size_t>(p); } + size_t operator() (T *p) const { return reinterpret_cast<size_t> (p); } }; -} +} // namespace __gnu_cxx #else -# define Unordered_map(KEYTYPE, VALTYPE) \ - std::map<KEYTYPE, VALTYPE> +#define Unordered_map(KEYTYPE, VALTYPE) std::map<KEYTYPE, VALTYPE> -# define Unordered_set(KEYTYPE) \ - std::set<KEYTYPE> +#define Unordered_set(KEYTYPE) std::set<KEYTYPE> // We could make this work by writing an adapter class which // implemented operator< in terms of the hash function. -# error "requires hash table type" +#error "requires hash table type" #endif @@ -142,17 +132,19 @@ struct hash<T*> #include "ansidecl.h" #include "coretypes.h" -#include "diagnostic-core.h" /* For error_at and friends. */ -#include "intl.h" /* For _(). */ +#include "diagnostic-core.h" /* For error_at and friends. */ +#include "intl.h" /* For _(). */ // When using gcc, rust_assert is just gcc_assert. -#define rust_assert(EXPR) gcc_assert(EXPR) +#define rust_assert(EXPR) gcc_assert (EXPR) // When using gcc, rust_unreachable is just gcc_unreachable. -#define rust_unreachable() gcc_unreachable() +#define rust_unreachable() gcc_unreachable () -extern void rust_preserve_from_gc (tree t); +extern void +rust_preserve_from_gc (tree t); -extern const char* rust_localize_identifier (const char *ident); +extern const char * +rust_localize_identifier (const char *ident); #endif // !defined(RUST_SYSTEM_H) diff --git a/gcc/rust/rustspec.cc b/gcc/rust/rustspec.cc index b61114f..28c2d9a 100644 --- a/gcc/rust/rustspec.cc +++ b/gcc/rust/rustspec.cc @@ -1,5 +1,5 @@ /* rustspec.c -- Specific flags and argument handling of the gcc Go front end. - Copyright (C) 2009-2019 Free Software Foundation, Inc. + Copyright (C) 2009-2020 Free Software Foundation, Inc. This file is part of GCC. @@ -340,7 +340,7 @@ lang_specific_driver (struct cl_decoded_option **in_decoded_options, if (library > 0) { // generate_option (OPT_l, LIBGOBEGIN, 1, CL_DRIVER, - // &new_decoded_options[j]); + // &new_decoded_options[j]); // added_libraries++; // j++; |