diff options
author | SimplyTheOther <simplytheother@gmail.com> | 2020-12-18 21:33:09 +0800 |
---|---|---|
committer | SimplyTheOther <simplytheother@gmail.com> | 2020-12-18 21:33:09 +0800 |
commit | aa283484a3dffedc404653af18f9413775cbc3df (patch) | |
tree | 118a5b918c48fba3261731bba0a6b4149209f7d8 /gcc | |
parent | f764eeb8abf1ec50794ddb1f31bc57d025e29a3c (diff) | |
parent | bc14d9a0cd3c67093a9c11ad368c0d28325b21c6 (diff) | |
download | gcc-aa283484a3dffedc404653af18f9413775cbc3df.zip gcc-aa283484a3dffedc404653af18f9413775cbc3df.tar.gz gcc-aa283484a3dffedc404653af18f9413775cbc3df.tar.bz2 |
Merge branch 'master' of https://github.com/redbrain/gccrs
Diffstat (limited to 'gcc')
79 files changed, 26740 insertions, 6689 deletions
diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 234d51b..5ac60ea 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -69,11 +69,16 @@ GRS_OBJS = \ rust/rust-parse.o \ rust/rust-ast-full-test.o \ rust/rust-session-manager.o \ - rust/rust-name-resolution.o \ - rust/rust-type-resolution.o \ - rust/rust-scan.o \ rust/rust-compile.o \ + rust/rust-compile-resolve-path.o \ rust/rust-macro-expand.o \ + rust/rust-hir-full-test.o \ + rust/rust-hir-map.o \ + rust/rust-ast-lower.o \ + rust/rust-ast-resolve.o \ + rust/rust-hir-type-check.o \ + rust/rust-tyty.o \ + rust/rust-tyctx.o \ $(END) # removed object files from here @@ -217,7 +222,18 @@ CFLAGS-rust/rust-lang.o += -DDEFAULT_TARGET_VERSION=\"$(version)\" \ -DDEFAULT_TARGET_MACHINE=\"$(target_noncanonical)\" # cross-folder includes - add new folders later -RUST_INCLUDES = -I $(srcdir)/rust -I $(srcdir)/rust/lex -I $(srcdir)/rust/parse -I $(srcdir)/rust/ast -I $(srcdir)/rust/analysis -I $(srcdir)/rust/backend -I $(srcdir)/rust/expand +RUST_INCLUDES = -I $(srcdir)/rust \ + -I $(srcdir)/rust/lex \ + -I $(srcdir)/rust/parse \ + -I $(srcdir)/rust/ast \ + -I $(srcdir)/rust/analysis \ + -I $(srcdir)/rust/backend \ + -I $(srcdir)/rust/expand \ + -I $(srcdir)/rust/hir/tree \ + -I $(srcdir)/rust/hir \ + -I $(srcdir)/rust/resolve \ + -I $(srcdir)/rust/util \ + -I $(srcdir)/rust/typecheck # add files that require cross-folder includes - currently rust-lang.o, rust-lex.o CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES) @@ -226,33 +242,55 @@ CFLAGS-rust/rust-parse.o += $(RUST_INCLUDES) CFLAGS-rust/rust-session-manager.o += $(RUST_INCLUDES) # TODO: possibly find a way to ensure C++11 compilation level here? +RUST_CXXFLAGS = -std=c++11 -Wno-unused-parameter -Wno-overloaded-virtual # build all rust/lex files in rust folder, add cross-folder includes rust/%.o: rust/lex/%.cc - $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) # build all rust/parse files in rust folder, add cross-folder includes rust/%.o: rust/parse/%.cc - $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) # build rust/ast files in rust folder rust/%.o: rust/ast/%.cc - $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< - $(POSTCOMPILE) - -# build rust/analysis files in rust folder -rust/%.o: rust/analysis/%.cc - $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) # build rust/backend files in rust folder rust/%.o: rust/backend/%.cc - $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) -# build rust/backend files in rust folder +# build rust/expand files in rust folder rust/%.o: rust/expand/%.cc - $(COMPILE) -std=c++11 $(RUST_INCLUDES) $< + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) + +# build rust/util files in rust folder +rust/%.o: rust/util/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) + +# build rust/hir files in rust folder +rust/%.o: rust/hir/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) + +# build rust/hir/tree files in rust folder +rust/%.o: rust/hir/tree/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) + +# build rust/resolve files in rust folder +rust/%.o: rust/resolve/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) + +# build rust/typecheck files in rust folder +rust/%.o: rust/typecheck/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) + diff --git a/gcc/rust/analysis/rust-name-resolution.cc b/gcc/rust/analysis/rust-name-resolution.cc deleted file mode 100644 index 28a4af8..0000000 --- a/gcc/rust/analysis/rust-name-resolution.cc +++ /dev/null @@ -1,657 +0,0 @@ -#include "rust-name-resolution.h" -#include "rust-diagnostics.h" - -/* - * The principles of name resolution: - * 1. If a name resolves to a binding then it should always resolve to that - * binding, and if resolving a name produces an error, it should always produce - * an error. - * 2. Avoid errors due to the resolver being stuck. - * 3. Names should be able to be used before they are declared, but the order of - * declarations should be irrelevant. - * 4. Macros should be hygiene and manually expandable. - * 5. Glob imports should be manually expandable. - */ - -/* The algorithm of name resolution - * 1. When encouter items which bind a name, add the name to the binding table. - * 2. When we find an import which can't be resolved, we add it to a work list. - * 3. When we find a glob import, we have to record a 'back link', so that when - * a public name is added for the supplying module, we can add it for the - * importing module. - * 4. Loop over the work list and try to lookup names. - * a. If a name has exactly one best binding then we use it (and record the - * binding on a list of resolved names). - * b. If there are zero then we put it back on the work list. - * c. If there is more than one binding, then we record an ambiguity error. - * d. When the work list no longer changes, then we are done. - * e. If the work list is empty, then expansion/import resolution succeeded. - * Otherwise there are names not found, or ambiguous names, then failed. - * 5. When looking up names, we record the resolutions in the binding table. - * a. If the name a glob import, we add bindings for every accessible name - * currently known. - * 6. To expand a macro, we try to resolve the macro's name. - * a. If that fails, we put it on the work list. - * Otherwise, we expand that macro by parsing the arguments, - * pattern matching, and doing hygienic expansion. - * b. We then parse the generated code in the same way as we parsed the - * original program. We add new names to the binding table, and expand any - * new macro uses. - * 7. If we add names for a module which has back links, we must follow them and - * add these names to the importing module (if they are accessible). - */ - -namespace Rust { -namespace Analysis { - -NameResolution::NameResolution (AST::Crate &crate, TopLevelScan &toplevel) - : Resolution (crate, toplevel), is_work_list_changed_ (false) - -{} - -NameResolution::~NameResolution () {} - -bool -NameResolution::Resolve (AST::Crate &crate, TopLevelScan &toplevel) -{ - NameResolution resolver (crate, toplevel); - return resolver.go (); -} - -void -NameResolution::process_work_list () -{} - -void -NameResolution::expand_macros () -{} - -bool -NameResolution::go () -{ - bool ret = true; - - do - { - for (auto &item : crate.items) - { - item->accept_vis (*this); - } - } - while (is_work_list_changed ()); - - ret = work_list_.empty (); - for (auto &item : work_list_) - { - std::cout << "Resolution error: " << item.as_string () << std::endl; - } - - return ret; -} - -void -NameResolution::visit (AST::Token &tok) -{} - -void -NameResolution::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -NameResolution::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -NameResolution::visit (AST::IdentifierExpr &ident_expr) -{ - do - { - process_work_list (); - } - while (is_work_list_changed ()); - expand_macros (); -} - -void -NameResolution::visit (AST::Lifetime &lifetime) -{} - -void -NameResolution::visit (AST::LifetimeParam &lifetime_param) -{} - -void -NameResolution::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -NameResolution::visit (AST::PathInExpression &path) -{} - -void -NameResolution::visit (AST::TypePathSegment &segment) -{} -void -NameResolution::visit (AST::TypePathSegmentGeneric &segment) -{} - -void -NameResolution::visit (AST::TypePathSegmentFunction &segment) -{} - -void -NameResolution::visit (AST::TypePath &path) -{} - -void -NameResolution::visit (AST::QualifiedPathInExpression &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -NameResolution::visit (AST::QualifiedPathInType &path) -{} - -// rust-expr.h -void -NameResolution::visit (AST::LiteralExpr &expr) -{} - -void -NameResolution::visit (AST::AttrInputLiteral &attr_input) -{} - -void -NameResolution::visit (AST::MetaItemLitExpr &meta_item) -{} - -void -NameResolution::visit (AST::MetaItemPathLit &meta_item) -{} - -void -NameResolution::visit (AST::BorrowExpr &expr) -{} -void -NameResolution::visit (AST::DereferenceExpr &expr) -{} -void -NameResolution::visit (AST::ErrorPropagationExpr &expr) -{} -void -NameResolution::visit (AST::NegationExpr &expr) -{} - -void -NameResolution::visit (AST::ArithmeticOrLogicalExpr &expr) -{} - -void -NameResolution::visit (AST::ComparisonExpr &expr) -{} - -void -NameResolution::visit (AST::LazyBooleanExpr &expr) -{} - -void -NameResolution::visit (AST::TypeCastExpr &expr) -{} - -void -NameResolution::visit (AST::AssignmentExpr &expr) -{} - -void -NameResolution::visit (AST::CompoundAssignmentExpr &expr) -{} - -void -NameResolution::visit (AST::GroupedExpr &expr) -{} -// void NameResolution::visit(ArrayElems& elems) {} -void -NameResolution::visit (AST::ArrayElemsValues &elems) -{} -void -NameResolution::visit (AST::ArrayElemsCopied &elems) -{} -void -NameResolution::visit (AST::ArrayExpr &expr) -{} -void -NameResolution::visit (AST::ArrayIndexExpr &expr) -{} -void -NameResolution::visit (AST::TupleExpr &expr) -{} -void -NameResolution::visit (AST::TupleIndexExpr &expr) -{} -void -NameResolution::visit (AST::StructExprStruct &expr) -{} -// void NameResolution::visit(StructExprField& field) {} -void -NameResolution::visit (AST::StructExprFieldIdentifier &field) -{} -void -NameResolution::visit (AST::StructExprFieldIdentifierValue &field) -{} -void -NameResolution::visit (AST::StructExprFieldIndexValue &field) -{} -void -NameResolution::visit (AST::StructExprStructFields &expr) -{} -void -NameResolution::visit (AST::StructExprStructBase &expr) -{} -void -NameResolution::visit (AST::StructExprTuple &expr) -{} -void -NameResolution::visit (AST::StructExprUnit &expr) -{} -// void NameResolution::visit(EnumExprField& field) {} -void -NameResolution::visit (AST::EnumExprFieldIdentifier &field) -{} -void -NameResolution::visit (AST::EnumExprFieldIdentifierValue &field) -{} -void -NameResolution::visit (AST::EnumExprFieldIndexValue &field) -{} -void -NameResolution::visit (AST::EnumExprStruct &expr) -{} -void -NameResolution::visit (AST::EnumExprTuple &expr) -{} -void -NameResolution::visit (AST::EnumExprFieldless &expr) -{} - -void -NameResolution::visit (AST::CallExpr &expr) -{} - -void -NameResolution::visit (AST::MethodCallExpr &expr) -{} -void -NameResolution::visit (AST::FieldAccessExpr &expr) -{} -void -NameResolution::visit (AST::ClosureExprInner &expr) -{} -void -NameResolution::visit (AST::BlockExpr &expr) -{} -void -NameResolution::visit (AST::ClosureExprInnerTyped &expr) -{} -void -NameResolution::visit (AST::ContinueExpr &expr) -{} -void -NameResolution::visit (AST::BreakExpr &expr) -{} -void -NameResolution::visit (AST::RangeFromToExpr &expr) -{} -void -NameResolution::visit (AST::RangeFromExpr &expr) -{} -void -NameResolution::visit (AST::RangeToExpr &expr) -{} -void -NameResolution::visit (AST::RangeFullExpr &expr) -{} -void -NameResolution::visit (AST::RangeFromToInclExpr &expr) -{} -void -NameResolution::visit (AST::RangeToInclExpr &expr) -{} -void -NameResolution::visit (AST::ReturnExpr &expr) -{} -void -NameResolution::visit (AST::UnsafeBlockExpr &expr) -{} -void -NameResolution::visit (AST::LoopExpr &expr) -{} -void -NameResolution::visit (AST::WhileLoopExpr &expr) -{} -void -NameResolution::visit (AST::WhileLetLoopExpr &expr) -{} -void -NameResolution::visit (AST::ForLoopExpr &expr) -{} -void -NameResolution::visit (AST::IfExpr &expr) -{} -void -NameResolution::visit (AST::IfExprConseqElse &expr) -{} -void -NameResolution::visit (AST::IfExprConseqIf &expr) -{} -void -NameResolution::visit (AST::IfExprConseqIfLet &expr) -{} -void -NameResolution::visit (AST::IfLetExpr &expr) -{} -void -NameResolution::visit (AST::IfLetExprConseqElse &expr) -{} -void -NameResolution::visit (AST::IfLetExprConseqIf &expr) -{} -void -NameResolution::visit (AST::IfLetExprConseqIfLet &expr) -{} -// void NameResolution::visit(MatchCase& match_case) {} -/*void -NameResolution::visit (AST::MatchCaseBlockExpr &match_case) -{}*/ -/*void -NameResolution::visit (AST::MatchCaseExpr &match_case) -{}*/ -void -NameResolution::visit (AST::MatchExpr &expr) -{} -void -NameResolution::visit (AST::AwaitExpr &expr) -{} -void -NameResolution::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -NameResolution::visit (AST::TypeParam ¶m) -{} -// void NameResolution::visit(WhereClauseItem& item) {} -void -NameResolution::visit (AST::LifetimeWhereClauseItem &item) -{} -void -NameResolution::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -NameResolution::visit (AST::Method &method) -{} -void -NameResolution::visit (AST::ModuleBodied &module) -{} -void -NameResolution::visit (AST::ModuleNoBody &module) -{} -void -NameResolution::visit (AST::ExternCrate &crate) -{} -// void NameResolution::visit(UseTree& use_tree) {} -void -NameResolution::visit (AST::UseTreeGlob &use_tree) -{} -void -NameResolution::visit (AST::UseTreeList &use_tree) -{} -void -NameResolution::visit (AST::UseTreeRebind &use_tree) -{} -void -NameResolution::visit (AST::UseDeclaration &use_decl) -{} - -void -NameResolution::visit (AST::Function &function) -{} - -void -NameResolution::visit (AST::TypeAlias &type_alias) -{} -void -NameResolution::visit (AST::StructStruct &struct_item) -{} -void -NameResolution::visit (AST::TupleStruct &tuple_struct) -{} -void -NameResolution::visit (AST::EnumItem &item) -{} -void -NameResolution::visit (AST::EnumItemTuple &item) -{} -void -NameResolution::visit (AST::EnumItemStruct &item) -{} -void -NameResolution::visit (AST::EnumItemDiscriminant &item) -{} -void -NameResolution::visit (AST::Enum &enum_item) -{} -void -NameResolution::visit (AST::Union &union_item) -{} - -void -NameResolution::visit (AST::ConstantItem &const_item) -{} - -void -NameResolution::visit (AST::StaticItem &static_item) -{} -void -NameResolution::visit (AST::TraitItemFunc &item) -{} -void -NameResolution::visit (AST::TraitItemMethod &item) -{} -void -NameResolution::visit (AST::TraitItemConst &item) -{} -void -NameResolution::visit (AST::TraitItemType &item) -{} -void -NameResolution::visit (AST::Trait &trait) -{} -void -NameResolution::visit (AST::InherentImpl &impl) -{} -void -NameResolution::visit (AST::TraitImpl &impl) -{} -// void NameResolution::visit(ExternalItem& item) {} -void -NameResolution::visit (AST::ExternalStaticItem &item) -{} -void -NameResolution::visit (AST::ExternalFunctionItem &item) -{} -void -NameResolution::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -NameResolution::visit (AST::MacroMatchFragment &match) -{} -void -NameResolution::visit (AST::MacroMatchRepetition &match) -{} -void -NameResolution::visit (AST::MacroMatcher &matcher) -{} - -void -NameResolution::visit (AST::MacroRulesDefinition &rules_def) -{} - -void -NameResolution::visit (AST::MacroInvocation ¯o_invoc) -{} -void -NameResolution::visit (AST::MetaItemPath &meta_item) -{} -void -NameResolution::visit (AST::MetaItemSeq &meta_item) -{} -void -NameResolution::visit (AST::MetaWord &meta_item) -{} -void -NameResolution::visit (AST::MetaNameValueStr &meta_item) -{} -void -NameResolution::visit (AST::MetaListPaths &meta_item) -{} -void -NameResolution::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -NameResolution::visit (AST::LiteralPattern &pattern) -{} - -void -NameResolution::visit (AST::IdentifierPattern &pattern) -{} - -void -NameResolution::visit (AST::WildcardPattern &pattern) -{} -// void NameResolution::visit(RangePatternBound& bound) {} -void -NameResolution::visit (AST::RangePatternBoundLiteral &bound) -{} -void -NameResolution::visit (AST::RangePatternBoundPath &bound) -{} -void -NameResolution::visit (AST::RangePatternBoundQualPath &bound) -{} -void -NameResolution::visit (AST::RangePattern &pattern) -{} -void -NameResolution::visit (AST::ReferencePattern &pattern) -{} -// void NameResolution::visit(StructPatternField& field) {} -void -NameResolution::visit (AST::StructPatternFieldTuplePat &field) -{} -void -NameResolution::visit (AST::StructPatternFieldIdentPat &field) -{} -void -NameResolution::visit (AST::StructPatternFieldIdent &field) -{} -void -NameResolution::visit (AST::StructPattern &pattern) -{} -// void NameResolution::visit(TupleStructItems& tuple_items) {} -void -NameResolution::visit (AST::TupleStructItemsNoRange &tuple_items) -{} -void -NameResolution::visit (AST::TupleStructItemsRange &tuple_items) -{} -void -NameResolution::visit (AST::TupleStructPattern &pattern) -{} -// void NameResolution::visit(TuplePatternItems& tuple_items) {} -void -NameResolution::visit (AST::TuplePatternItemsMultiple &tuple_items) -{} -void -NameResolution::visit (AST::TuplePatternItemsRanged &tuple_items) -{} -void -NameResolution::visit (AST::TuplePattern &pattern) -{} -void -NameResolution::visit (AST::GroupedPattern &pattern) -{} -void -NameResolution::visit (AST::SlicePattern &pattern) -{} - -// rust-stmt.h -void -NameResolution::visit (AST::EmptyStmt &stmt) -{} - -void -NameResolution::visit (AST::LetStmt &stmt) -{} - -void -NameResolution::visit (AST::ExprStmtWithoutBlock &stmt) -{} - -void -NameResolution::visit (AST::ExprStmtWithBlock &stmt) -{} - -// rust-type.h -void -NameResolution::visit (AST::TraitBound &bound) -{} - -void -NameResolution::visit (AST::ImplTraitType &type) -{} - -void -NameResolution::visit (AST::TraitObjectType &type) -{} -void -NameResolution::visit (AST::ParenthesisedType &type) -{} -void -NameResolution::visit (AST::ImplTraitTypeOneBound &type) -{} -void -NameResolution::visit (AST::TraitObjectTypeOneBound &type) -{} -void -NameResolution::visit (AST::TupleType &type) -{} -void -NameResolution::visit (AST::NeverType &type) -{} -void -NameResolution::visit (AST::RawPointerType &type) -{} -void -NameResolution::visit (AST::ReferenceType &type) -{} -void -NameResolution::visit (AST::ArrayType &type) -{} -void -NameResolution::visit (AST::SliceType &type) -{} -void -NameResolution::visit (AST::InferredType &type) -{} -void -NameResolution::visit (AST::BareFunctionType &type) -{} - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-name-resolution.h b/gcc/rust/analysis/rust-name-resolution.h deleted file mode 100644 index b3bc780..0000000 --- a/gcc/rust/analysis/rust-name-resolution.h +++ /dev/null @@ -1,232 +0,0 @@ -#pragma once - -#include "rust-resolution.h" -#include <list> - -namespace Rust { -namespace Analysis { - -class NameResolution : public Resolution -{ -public: - ~NameResolution (); - static bool Resolve (AST::Crate &crate, TopLevelScan &toplevel); - - // visitor impl - // rust-ast.h - // void visit(AttrInput& attr_input); - // void visit(TokenTree& token_tree); - // void visit(MacroMatch& macro_match); - void visit (AST::Token &tok) override; - void visit (AST::DelimTokenTree &delim_tok_tree) override; - void visit (AST::AttrInputMetaItemContainer &input) override; - // void visit(MetaItem& meta_item) override; - // void vsit(Stmt& stmt) override; - // void visit(Expr& expr) override; - void visit (AST::IdentifierExpr &ident_expr) override; - // void visit(Pattern& pattern) override; - // void visit(Type& type) override; - // void visit(TypeParamBound& type_param_bound) override; - void visit (AST::Lifetime &lifetime) override; - // void visit(GenericParam& generic_param) override; - void visit (AST::LifetimeParam &lifetime_param) override; - // void visit(TraitItem& trait_item) override; - // void visit(InherentImplItem& inherent_impl_item) override; - // void visit(TraitImplItem& trait_impl_item) override; - void visit (AST::MacroInvocationSemi ¯o) override; - - // rust-path.h - void visit (AST::PathInExpression &path) override; - void visit (AST::TypePathSegment &segment) override; - void visit (AST::TypePathSegmentGeneric &segment) override; - void visit (AST::TypePathSegmentFunction &segment) override; - void visit (AST::TypePath &path) override; - void visit (AST::QualifiedPathInExpression &path) override; - void visit (AST::QualifiedPathInType &path) override; - - // rust-expr.h - void visit (AST::LiteralExpr &expr) override; - void visit (AST::AttrInputLiteral &attr_input) override; - void visit (AST::MetaItemLitExpr &meta_item) override; - void visit (AST::MetaItemPathLit &meta_item) override; - void visit (AST::BorrowExpr &expr) override; - void visit (AST::DereferenceExpr &expr) override; - void visit (AST::ErrorPropagationExpr &expr) override; - void visit (AST::NegationExpr &expr) override; - void visit (AST::ArithmeticOrLogicalExpr &expr) override; - void visit (AST::ComparisonExpr &expr) override; - void visit (AST::LazyBooleanExpr &expr) override; - void visit (AST::TypeCastExpr &expr) override; - void visit (AST::AssignmentExpr &expr) override; - void visit (AST::CompoundAssignmentExpr &expr) override; - void visit (AST::GroupedExpr &expr) override; - // void visit(ArrayElems& elems) override; - void visit (AST::ArrayElemsValues &elems) override; - void visit (AST::ArrayElemsCopied &elems) override; - void visit (AST::ArrayExpr &expr) override; - void visit (AST::ArrayIndexExpr &expr) override; - void visit (AST::TupleExpr &expr) override; - void visit (AST::TupleIndexExpr &expr) override; - void visit (AST::StructExprStruct &expr) override; - // void visit(StructExprField& field) override; - void visit (AST::StructExprFieldIdentifier &field) override; - void visit (AST::StructExprFieldIdentifierValue &field) override; - void visit (AST::StructExprFieldIndexValue &field) override; - void visit (AST::StructExprStructFields &expr) override; - void visit (AST::StructExprStructBase &expr) override; - void visit (AST::StructExprTuple &expr) override; - void visit (AST::StructExprUnit &expr) override; - // void visit(EnumExprField& field) override; - void visit (AST::EnumExprFieldIdentifier &field) override; - void visit (AST::EnumExprFieldIdentifierValue &field) override; - void visit (AST::EnumExprFieldIndexValue &field) override; - void visit (AST::EnumExprStruct &expr) override; - void visit (AST::EnumExprTuple &expr) override; - void visit (AST::EnumExprFieldless &expr) override; - void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; - void visit (AST::FieldAccessExpr &expr) override; - void visit (AST::ClosureExprInner &expr) override; - void visit (AST::BlockExpr &expr) override; - void visit (AST::ClosureExprInnerTyped &expr) override; - void visit (AST::ContinueExpr &expr) override; - void visit (AST::BreakExpr &expr) override; - void visit (AST::RangeFromToExpr &expr) override; - void visit (AST::RangeFromExpr &expr) override; - void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &expr) override; - void visit (AST::RangeFromToInclExpr &expr) override; - void visit (AST::RangeToInclExpr &expr) override; - void visit (AST::ReturnExpr &expr) override; - void visit (AST::UnsafeBlockExpr &expr) override; - void visit (AST::LoopExpr &expr) override; - void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::WhileLetLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; - void visit (AST::IfExpr &expr) override; - void visit (AST::IfExprConseqElse &expr) override; - void visit (AST::IfExprConseqIf &expr) override; - void visit (AST::IfExprConseqIfLet &expr) override; - void visit (AST::IfLetExpr &expr) override; - void visit (AST::IfLetExprConseqElse &expr) override; - void visit (AST::IfLetExprConseqIf &expr) override; - void visit (AST::IfLetExprConseqIfLet &expr) override; - // void visit(MatchCase& match_case) override; - // void visit (AST::MatchCaseBlockExpr &match_case) override; - // void visit (AST::MatchCaseExpr &match_case) override; - void visit (AST::MatchExpr &expr) override; - void visit (AST::AwaitExpr &expr) override; - void visit (AST::AsyncBlockExpr &expr) override; - - // rust-item.h - void visit (AST::TypeParam ¶m) override; - // void visit(WhereClauseItem& item) override; - void visit (AST::LifetimeWhereClauseItem &item) override; - void visit (AST::TypeBoundWhereClauseItem &item) override; - void visit (AST::Method &method) override; - void visit (AST::ModuleBodied &module) override; - void visit (AST::ModuleNoBody &module) override; - void visit (AST::ExternCrate &crate) override; - // void visit(UseTree& use_tree) override; - void visit (AST::UseTreeGlob &use_tree) override; - void visit (AST::UseTreeList &use_tree) override; - void visit (AST::UseTreeRebind &use_tree) override; - void visit (AST::UseDeclaration &use_decl) override; - void visit (AST::Function &function) override; - void visit (AST::TypeAlias &type_alias) override; - void visit (AST::StructStruct &struct_item) override; - void visit (AST::TupleStruct &tuple_struct) override; - void visit (AST::EnumItem &item) override; - void visit (AST::EnumItemTuple &item) override; - void visit (AST::EnumItemStruct &item) override; - void visit (AST::EnumItemDiscriminant &item) override; - void visit (AST::Enum &enum_item) override; - void visit (AST::Union &union_item) override; - void visit (AST::ConstantItem &const_item) override; - void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemFunc &item) override; - void visit (AST::TraitItemMethod &item) override; - void visit (AST::TraitItemConst &item) override; - void visit (AST::TraitItemType &item) override; - void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl) override; - void visit (AST::TraitImpl &impl) override; - // void visit(ExternalItem& item) override; - void visit (AST::ExternalStaticItem &item) override; - void visit (AST::ExternalFunctionItem &item) override; - void visit (AST::ExternBlock &block) override; - - // rust-macro.h - void visit (AST::MacroMatchFragment &match) override; - void visit (AST::MacroMatchRepetition &match) override; - void visit (AST::MacroMatcher &matcher) override; - void visit (AST::MacroRulesDefinition &rules_def) override; - void visit (AST::MacroInvocation ¯o_invoc) override; - void visit (AST::MetaItemPath &meta_item) override; - void visit (AST::MetaItemSeq &meta_item) override; - void visit (AST::MetaWord &meta_item) override; - void visit (AST::MetaNameValueStr &meta_item) override; - void visit (AST::MetaListPaths &meta_item) override; - void visit (AST::MetaListNameValueStr &meta_item) override; - - // rust-pattern.h - void visit (AST::LiteralPattern &pattern) override; - void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::WildcardPattern &pattern) override; - // void visit(RangePatternBound& bound) override; - void visit (AST::RangePatternBoundLiteral &bound) override; - void visit (AST::RangePatternBoundPath &bound) override; - void visit (AST::RangePatternBoundQualPath &bound) override; - void visit (AST::RangePattern &pattern) override; - void visit (AST::ReferencePattern &pattern) override; - // void visit(StructPatternField& field) override; - void visit (AST::StructPatternFieldTuplePat &field) override; - void visit (AST::StructPatternFieldIdentPat &field) override; - void visit (AST::StructPatternFieldIdent &field) override; - void visit (AST::StructPattern &pattern) override; - // void visit(TupleStructItems& tuple_items) override; - void visit (AST::TupleStructItemsNoRange &tuple_items) override; - void visit (AST::TupleStructItemsRange &tuple_items) override; - void visit (AST::TupleStructPattern &pattern) override; - // void visit(TuplePatternItems& tuple_items) override; - void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - void visit (AST::TuplePatternItemsRanged &tuple_items) override; - void visit (AST::TuplePattern &pattern) override; - void visit (AST::GroupedPattern &pattern) override; - void visit (AST::SlicePattern &pattern) override; - - // rust-stmt.h - void visit (AST::EmptyStmt &stmt) override; - void visit (AST::LetStmt &stmt) override; - void visit (AST::ExprStmtWithoutBlock &stmt) override; - void visit (AST::ExprStmtWithBlock &stmt) override; - - // rust-type.h - void visit (AST::TraitBound &bound) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::TraitObjectType &type) override; - void visit (AST::ParenthesisedType &type) override; - void visit (AST::ImplTraitTypeOneBound &type) override; - void visit (AST::TraitObjectTypeOneBound &type) override; - void visit (AST::TupleType &type) override; - void visit (AST::NeverType &type) override; - void visit (AST::RawPointerType &type) override; - void visit (AST::ReferenceType &type) override; - void visit (AST::ArrayType &type) override; - void visit (AST::SliceType &type) override; - void visit (AST::InferredType &type) override; - void visit (AST::BareFunctionType &type) override; - -private: - NameResolution (AST::Crate &crate, TopLevelScan &toplevel); - bool go () override; - void process_names (); - void process_work_list (); - void expand_macros (); - bool is_work_list_changed () { return is_work_list_changed_; } - std::list<AST::UseDeclaration> work_list_; - bool is_work_list_changed_; -}; - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-resolution.cc b/gcc/rust/analysis/rust-resolution.cc deleted file mode 100644 index 731801a..0000000 --- a/gcc/rust/analysis/rust-resolution.cc +++ /dev/null @@ -1,867 +0,0 @@ -#include "rust-resolution.h" -#include "rust-diagnostics.h" - -#define ADD_BUILTIN_TYPE(_X, _S) \ - do \ - { \ - AST::PathIdentSegment seg (_X); \ - auto typePath = ::std::unique_ptr<AST::TypePathSegment> ( \ - new AST::TypePathSegment (::std::move (seg), false, \ - Linemap::unknown_location ())); \ - ::std::vector< ::std::unique_ptr<AST::TypePathSegment> > segs; \ - segs.push_back (::std::move (typePath)); \ - auto bType = new AST::TypePath (::std::move (segs), \ - Linemap::unknown_location (), false); \ - _S.Insert (_X, bType); \ - } \ - while (0) - -namespace Rust { -namespace Analysis { - -TypeResolution::TypeResolution (AST::Crate &crate, TopLevelScan &toplevel) - : crate (crate), toplevel (toplevel) -{ - typeScope.Push (); - scope.Push (); - - // push all builtin types - this is probably too basic for future needs - ADD_BUILTIN_TYPE ("u8", typeScope); - ADD_BUILTIN_TYPE ("u16", typeScope); - ADD_BUILTIN_TYPE ("u32", typeScope); - ADD_BUILTIN_TYPE ("u64", typeScope); - - ADD_BUILTIN_TYPE ("i8", typeScope); - ADD_BUILTIN_TYPE ("i16", typeScope); - ADD_BUILTIN_TYPE ("i32", typeScope); - ADD_BUILTIN_TYPE ("i64", typeScope); - - ADD_BUILTIN_TYPE ("f32", typeScope); - ADD_BUILTIN_TYPE ("f64", typeScope); - - ADD_BUILTIN_TYPE ("char", typeScope); - ADD_BUILTIN_TYPE ("str", typeScope); - ADD_BUILTIN_TYPE ("bool", typeScope); -} - -TypeResolution::~TypeResolution () -{ - typeScope.Pop (); - scope.Pop (); -} - -bool -TypeResolution::ResolveNamesAndTypes (AST::Crate &crate, TopLevelScan &toplevel) -{ - TypeResolution resolver (crate, toplevel); - return resolver.go (); -} - -bool -TypeResolution::go () -{ - for (auto &item : crate.items) - item->accept_vis (*this); - - return true; -} - -bool -TypeResolution::typesAreCompatible (AST::Type *lhs, AST::Type *rhs, - Location locus) -{ - lhs->accept_vis (*this); - rhs->accept_vis (*this); - - auto rhsTypeStr = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - auto lhsTypeStr = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - // FIXME this needs to handle the cases of an i8 going into an i32 which is - // compatible - if (lhsTypeStr.compare (rhsTypeStr)) - { - rust_error_at (locus, "E0308: expected: %s, found %s", - lhsTypeStr.c_str (), rhsTypeStr.c_str ()); - return false; - } - - return true; -} - -void -TypeResolution::visit (AST::Token &tok) -{} - -void -TypeResolution::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -TypeResolution::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -TypeResolution::visit (AST::IdentifierExpr &ident_expr) -{ - AST::Type *type = NULL; - bool ok = scope.Lookup (ident_expr.ident, &type); - if (!ok) - { - rust_error_at (ident_expr.locus, "unknown identifier"); - return; - } - - typeBuffer.push_back (type); -} - -void -TypeResolution::visit (AST::Lifetime &lifetime) -{} - -void -TypeResolution::visit (AST::LifetimeParam &lifetime_param) -{} - -void -TypeResolution::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -TypeResolution::visit (AST::PathInExpression &path) -{ - printf ("PathInExpression: %s\n", path.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::TypePathSegment &segment) -{} -void -TypeResolution::visit (AST::TypePathSegmentGeneric &segment) -{} - -void -TypeResolution::visit (AST::TypePathSegmentFunction &segment) -{} - -void -TypeResolution::visit (AST::TypePath &path) -{ - // this may not be robust enough for type comparisons but lets try it for now - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -TypeResolution::visit (AST::QualifiedPathInExpression &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -TypeResolution::visit (AST::QualifiedPathInType &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -// rust-expr.h -void -TypeResolution::visit (AST::LiteralExpr &expr) -{ - std::string type; - switch (expr.literal.get_lit_type ()) - { - case AST::Literal::CHAR: - type = "char"; - break; - - case AST::Literal::STRING: - case AST::Literal::RAW_STRING: - type = "str"; - break; - - case AST::Literal::BOOL: - type = "bool"; - break; - - case AST::Literal::BYTE: - type = "u8"; - break; - - // FIXME these are not always going to be the case - // eg: suffix on the value can change the type - case AST::Literal::FLOAT: - type = "f32"; - break; - - case AST::Literal::INT: - type = "i32"; - break; - - case AST::Literal::BYTE_STRING: - case AST::Literal::RAW_BYTE_STRING: - // FIXME - break; - } - - if (type.empty ()) - { - rust_error_at (expr.locus, "unknown literal: %s", - expr.literal.as_string ().c_str ()); - return; - } - - AST::Type *val = NULL; - bool ok = typeScope.Lookup (type, &val); - if (ok) - typeBuffer.push_back (val); - else - rust_error_at (expr.locus, "unknown literal type: %s", type.c_str ()); -} - -void -TypeResolution::visit (AST::AttrInputLiteral &attr_input) -{} - -void -TypeResolution::visit (AST::MetaItemLitExpr &meta_item) -{} - -void -TypeResolution::visit (AST::MetaItemPathLit &meta_item) -{} - -void -TypeResolution::visit (AST::BorrowExpr &expr) -{} -void -TypeResolution::visit (AST::DereferenceExpr &expr) -{} -void -TypeResolution::visit (AST::ErrorPropagationExpr &expr) -{} -void -TypeResolution::visit (AST::NegationExpr &expr) -{} - -void -TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - size_t before; - before = typeBuffer.size (); - expr.visit_lhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.locus, "unable to determine lhs type"); - return; - } - - auto lhsType = typeBuffer.back (); - typeBuffer.pop_back (); - - before = typeBuffer.size (); - expr.visit_rhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.locus, "unable to determine rhs type"); - return; - } - - auto rhsType = typeBuffer.back (); - // not poping because we will be checking they match and the - // scope will require knowledge of the type - - // do the lhsType and the rhsType match - typesAreCompatible (lhsType, rhsType, expr.right_expr->get_locus_slow ()); -} - -void -TypeResolution::visit (AST::ComparisonExpr &expr) -{} - -void -TypeResolution::visit (AST::LazyBooleanExpr &expr) -{} - -void -TypeResolution::visit (AST::TypeCastExpr &expr) -{} - -void -TypeResolution::visit (AST::AssignmentExpr &expr) -{ - size_t before; - before = typeBuffer.size (); - expr.visit_lhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.locus, "unable to determine lhs type"); - return; - } - - auto lhsType = typeBuffer.back (); - typeBuffer.pop_back (); - - before = typeBuffer.size (); - expr.visit_rhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.locus, "unable to determine rhs type"); - return; - } - - auto rhsType = typeBuffer.back (); - // not poping because we will be checking they match and the - // scope will require knowledge of the type - - // do the lhsType and the rhsType match - if (!typesAreCompatible (lhsType, rhsType, - expr.right_expr->get_locus_slow ())) - return; - - // is the lhs mutable? -} - -void -TypeResolution::visit (AST::CompoundAssignmentExpr &expr) -{} - -void -TypeResolution::visit (AST::GroupedExpr &expr) -{} -// void TypeResolution::visit(ArrayElems& elems) {} -void -TypeResolution::visit (AST::ArrayElemsValues &elems) -{} -void -TypeResolution::visit (AST::ArrayElemsCopied &elems) -{} -void -TypeResolution::visit (AST::ArrayExpr &expr) -{} -void -TypeResolution::visit (AST::ArrayIndexExpr &expr) -{} -void -TypeResolution::visit (AST::TupleExpr &expr) -{} -void -TypeResolution::visit (AST::TupleIndexExpr &expr) -{} -void -TypeResolution::visit (AST::StructExprStruct &expr) -{} -// void TypeResolution::visit(StructExprField& field) {} -void -TypeResolution::visit (AST::StructExprFieldIdentifier &field) -{} -void -TypeResolution::visit (AST::StructExprFieldIdentifierValue &field) -{} -void -TypeResolution::visit (AST::StructExprFieldIndexValue &field) -{} -void -TypeResolution::visit (AST::StructExprStructFields &expr) -{} -void -TypeResolution::visit (AST::StructExprStructBase &expr) -{} -void -TypeResolution::visit (AST::StructExprTuple &expr) -{} -void -TypeResolution::visit (AST::StructExprUnit &expr) -{} -// void TypeResolution::visit(EnumExprField& field) {} -void -TypeResolution::visit (AST::EnumExprFieldIdentifier &field) -{} -void -TypeResolution::visit (AST::EnumExprFieldIdentifierValue &field) -{} -void -TypeResolution::visit (AST::EnumExprFieldIndexValue &field) -{} -void -TypeResolution::visit (AST::EnumExprStruct &expr) -{} -void -TypeResolution::visit (AST::EnumExprTuple &expr) -{} -void -TypeResolution::visit (AST::EnumExprFieldless &expr) -{} - -void -TypeResolution::visit (AST::CallExpr &expr) -{ - printf ("CallExpr: %s\n", expr.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::MethodCallExpr &expr) -{} -void -TypeResolution::visit (AST::FieldAccessExpr &expr) -{} -void -TypeResolution::visit (AST::ClosureExprInner &expr) -{} -void -TypeResolution::visit (AST::BlockExpr &expr) -{} -void -TypeResolution::visit (AST::ClosureExprInnerTyped &expr) -{} -void -TypeResolution::visit (AST::ContinueExpr &expr) -{} -void -TypeResolution::visit (AST::BreakExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromToExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromExpr &expr) -{} -void -TypeResolution::visit (AST::RangeToExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFullExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromToInclExpr &expr) -{} -void -TypeResolution::visit (AST::RangeToInclExpr &expr) -{} -void -TypeResolution::visit (AST::ReturnExpr &expr) -{} -void -TypeResolution::visit (AST::UnsafeBlockExpr &expr) -{} -void -TypeResolution::visit (AST::LoopExpr &expr) -{} -void -TypeResolution::visit (AST::WhileLoopExpr &expr) -{} -void -TypeResolution::visit (AST::WhileLetLoopExpr &expr) -{} -void -TypeResolution::visit (AST::ForLoopExpr &expr) -{} -void -TypeResolution::visit (AST::IfExpr &expr) -{} -void -TypeResolution::visit (AST::IfExprConseqElse &expr) -{} -void -TypeResolution::visit (AST::IfExprConseqIf &expr) -{} -void -TypeResolution::visit (AST::IfExprConseqIfLet &expr) -{} -void -TypeResolution::visit (AST::IfLetExpr &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqElse &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqIf &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqIfLet &expr) -{} -// void TypeResolution::visit(MatchCase& match_case) {} -void -TypeResolution::visit (AST::MatchCaseBlockExpr &match_case) -{} -void -TypeResolution::visit (AST::MatchCaseExpr &match_case) -{} -void -TypeResolution::visit (AST::MatchExpr &expr) -{} -void -TypeResolution::visit (AST::AwaitExpr &expr) -{} -void -TypeResolution::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -TypeResolution::visit (AST::TypeParam ¶m) -{} -// void TypeResolution::visit(WhereClauseItem& item) {} -void -TypeResolution::visit (AST::LifetimeWhereClauseItem &item) -{} -void -TypeResolution::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -TypeResolution::visit (AST::Method &method) -{} -void -TypeResolution::visit (AST::ModuleBodied &module) -{} -void -TypeResolution::visit (AST::ModuleNoBody &module) -{} -void -TypeResolution::visit (AST::ExternCrate &crate) -{} -// void TypeResolution::visit(UseTree& use_tree) {} -void -TypeResolution::visit (AST::UseTreeGlob &use_tree) -{} -void -TypeResolution::visit (AST::UseTreeList &use_tree) -{} -void -TypeResolution::visit (AST::UseTreeRebind &use_tree) -{} -void -TypeResolution::visit (AST::UseDeclaration &use_decl) -{} - -void -TypeResolution::visit (AST::Function &function) -{ - // always emit the function with return type in the event of nil return type - // its a marker for a void function - scope.Insert (function.function_name, function.return_type.get ()); - - scope.Push (); - for (auto ¶m : function.function_params) - { - auto before = letPatternBuffer.size (); - param.param_name->accept_vis (*this); - if (letPatternBuffer.size () <= before) - { - rust_error_at (param.locus, "failed to analyse parameter name"); - return; - } - - auto paramName = letPatternBuffer.back (); - letPatternBuffer.pop_back (); - scope.Insert (paramName.variable_ident, param.type.get ()); - } - - // walk the expression body - for (auto &stmt : function.function_body->statements) - { - stmt->accept_vis (*this); - } - - scope.Pop (); -} - -void -TypeResolution::visit (AST::TypeAlias &type_alias) -{} -void -TypeResolution::visit (AST::StructStruct &struct_item) -{} -void -TypeResolution::visit (AST::TupleStruct &tuple_struct) -{} -void -TypeResolution::visit (AST::EnumItem &item) -{} -void -TypeResolution::visit (AST::EnumItemTuple &item) -{} -void -TypeResolution::visit (AST::EnumItemStruct &item) -{} -void -TypeResolution::visit (AST::EnumItemDiscriminant &item) -{} -void -TypeResolution::visit (AST::Enum &enum_item) -{} -void -TypeResolution::visit (AST::Union &union_item) -{} - -void -TypeResolution::visit (AST::ConstantItem &const_item) -{ - printf ("ConstantItem: %s\n", const_item.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::StaticItem &static_item) -{} -void -TypeResolution::visit (AST::TraitItemFunc &item) -{} -void -TypeResolution::visit (AST::TraitItemMethod &item) -{} -void -TypeResolution::visit (AST::TraitItemConst &item) -{} -void -TypeResolution::visit (AST::TraitItemType &item) -{} -void -TypeResolution::visit (AST::Trait &trait) -{} -void -TypeResolution::visit (AST::InherentImpl &impl) -{} -void -TypeResolution::visit (AST::TraitImpl &impl) -{} -// void TypeResolution::visit(ExternalItem& item) {} -void -TypeResolution::visit (AST::ExternalStaticItem &item) -{} -void -TypeResolution::visit (AST::ExternalFunctionItem &item) -{} -void -TypeResolution::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -TypeResolution::visit (AST::MacroMatchFragment &match) -{} -void -TypeResolution::visit (AST::MacroMatchRepetition &match) -{} -void -TypeResolution::visit (AST::MacroMatcher &matcher) -{} -void -TypeResolution::visit (AST::MacroRulesDefinition &rules_def) -{} -void -TypeResolution::visit (AST::MacroInvocation ¯o_invoc) -{} -void -TypeResolution::visit (AST::MetaItemPath &meta_item) -{} -void -TypeResolution::visit (AST::MetaItemSeq &meta_item) -{} -void -TypeResolution::visit (AST::MetaWord &meta_item) -{} -void -TypeResolution::visit (AST::MetaNameValueStr &meta_item) -{} -void -TypeResolution::visit (AST::MetaListPaths &meta_item) -{} -void -TypeResolution::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -TypeResolution::visit (AST::LiteralPattern &pattern) -{ - printf ("LiteralPattern: %s\n", pattern.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::IdentifierPattern &pattern) -{ - letPatternBuffer.push_back (pattern); -} - -void -TypeResolution::visit (AST::WildcardPattern &pattern) -{} -// void TypeResolution::visit(RangePatternBound& bound) {} -void -TypeResolution::visit (AST::RangePatternBoundLiteral &bound) -{} -void -TypeResolution::visit (AST::RangePatternBoundPath &bound) -{} -void -TypeResolution::visit (AST::RangePatternBoundQualPath &bound) -{} -void -TypeResolution::visit (AST::RangePattern &pattern) -{} -void -TypeResolution::visit (AST::ReferencePattern &pattern) -{} -// void TypeResolution::visit(StructPatternField& field) {} -void -TypeResolution::visit (AST::StructPatternFieldTuplePat &field) -{} -void -TypeResolution::visit (AST::StructPatternFieldIdentPat &field) -{} -void -TypeResolution::visit (AST::StructPatternFieldIdent &field) -{} -void -TypeResolution::visit (AST::StructPattern &pattern) -{} -// void TypeResolution::visit(TupleStructItems& tuple_items) {} -void -TypeResolution::visit (AST::TupleStructItemsNoRange &tuple_items) -{} -void -TypeResolution::visit (AST::TupleStructItemsRange &tuple_items) -{} -void -TypeResolution::visit (AST::TupleStructPattern &pattern) -{} -// void TypeResolution::visit(TuplePatternItems& tuple_items) {} -void -TypeResolution::visit (AST::TuplePatternItemsMultiple &tuple_items) -{} -void -TypeResolution::visit (AST::TuplePatternItemsRanged &tuple_items) -{} -void -TypeResolution::visit (AST::TuplePattern &pattern) -{} -void -TypeResolution::visit (AST::GroupedPattern &pattern) -{} -void -TypeResolution::visit (AST::SlicePattern &pattern) -{} - -// rust-stmt.h -void -TypeResolution::visit (AST::EmptyStmt &stmt) -{} - -void -TypeResolution::visit (AST::LetStmt &stmt) -{ - if (!stmt.has_init_expr () && !stmt.has_type ()) - { - rust_error_at (stmt.locus, - "E0282: type annotations or init expression needed"); - return; - } - - AST::Type *inferedType = NULL; - if (stmt.has_init_expr ()) - { - stmt.init_expr->accept_vis (*this); - - if (typeBuffer.empty ()) - { - rust_error_at ( - stmt.init_expr->get_locus_slow (), - "unable to determine type for declaration from init expr"); - return; - } - - inferedType = typeBuffer.back (); - typeBuffer.pop_back (); - } - - if (stmt.has_type () && stmt.has_init_expr ()) - { - if (!typesAreCompatible (stmt.type.get (), inferedType, - stmt.init_expr->get_locus_slow ())) - { - return; - } - } - else if (stmt.has_type () && !stmt.has_init_expr ()) - { - inferedType = stmt.type.get (); - } - - // TODO check we know what the type is in the scope requires the builtins to - // be defined at the constructor - - // ensure the decl has the type set for compilation later on - if (!stmt.has_type ()) - { - // FIXME - // stmt.type = inferedType; - } - - // get all the names part of this declaration and add the types to the scope - stmt.variables_pattern->accept_vis (*this); - for (auto it = letPatternBuffer.begin (); it != letPatternBuffer.end (); it++) - { - scope.Insert (it->variable_ident, inferedType); - } - letPatternBuffer.clear (); -} - -void -TypeResolution::visit (AST::ExprStmtWithoutBlock &stmt) -{ - stmt.expr->accept_vis (*this); -} - -void -TypeResolution::visit (AST::ExprStmtWithBlock &stmt) -{} - -// rust-type.h -void -TypeResolution::visit (AST::TraitBound &bound) -{} - -void -TypeResolution::visit (AST::ImplTraitType &type) -{} - -void -TypeResolution::visit (AST::TraitObjectType &type) -{} -void -TypeResolution::visit (AST::ParenthesisedType &type) -{} -void -TypeResolution::visit (AST::ImplTraitTypeOneBound &type) -{} -void -TypeResolution::visit (AST::TraitObjectTypeOneBound &type) -{} -void -TypeResolution::visit (AST::TupleType &type) -{} -void -TypeResolution::visit (AST::NeverType &type) -{} -void -TypeResolution::visit (AST::RawPointerType &type) -{} -void -TypeResolution::visit (AST::ReferenceType &type) -{} -void -TypeResolution::visit (AST::ArrayType &type) -{} -void -TypeResolution::visit (AST::SliceType &type) -{} -void -TypeResolution::visit (AST::InferredType &type) -{} -void -TypeResolution::visit (AST::BareFunctionType &type) -{} - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-resolution.h b/gcc/rust/analysis/rust-resolution.h deleted file mode 100644 index 9eb4b95..0000000 --- a/gcc/rust/analysis/rust-resolution.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "rust-system.h" -#include "rust-ast-full.h" -#include "rust-ast-visitor.h" -#include "rust-scan.h" -#include "scope.h" - -namespace Rust { -namespace Analysis { - -class Resolution : public AST::ASTVisitor -{ -public: - virtual ~Resolution () - { - scope.Pop (); - valueScope.Pop (); - macroScope.Pop (); - typeScope.Pop (); - }; - -private: - virtual bool go () = 0; - -protected: - Resolution (AST::Crate &crate, TopLevelScan &toplevel) - : crate (crate), toplevel (toplevel) - { - scope.Push (); - valueScope.Push (); - macroScope.Push (); - typeScope.Push (); - }; - - Scope<AST::Type *> scope; - Scope<AST::Type *> valueScope; - Scope<AST::Type *> macroScope; - Scope<AST::Type *> typeScope; - - AST::Crate &crate; - TopLevelScan &toplevel; - - std::vector<AST::IdentifierPattern> letPatternBuffer; - std::vector<AST::Type *> typeBuffer; - std::vector<std::string> typeComparisonBuffer; - std::vector<AST::Function *> functionLookup; -}; - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-scan.cc b/gcc/rust/analysis/rust-scan.cc deleted file mode 100644 index 31c89e4..0000000 --- a/gcc/rust/analysis/rust-scan.cc +++ /dev/null @@ -1,593 +0,0 @@ -#include "rust-scan.h" -#include "rust-diagnostics.h" - -namespace Rust { -namespace Analysis { - -TopLevelScan::TopLevelScan (AST::Crate &crate) : crate (crate) -{ - for (auto &item : crate.items) - item->accept_vis (*this); -} - -TopLevelScan::~TopLevelScan () {} - -AST::Function * -TopLevelScan::lookupFunction (AST::Expr *expr) -{ - auto before = fnLookup.size (); - expr->accept_vis (*this); - if (fnLookup.size () > before) - { - AST::Function *fndecl = fnLookup.back (); - fnLookup.pop_back (); - return fndecl; - } - return NULL; -} - -void -TopLevelScan::visit (AST::Token &tok) -{} - -void -TopLevelScan::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -TopLevelScan::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -TopLevelScan::visit (AST::IdentifierExpr &ident_expr) -{} - -void -TopLevelScan::visit (AST::Lifetime &lifetime) -{} - -void -TopLevelScan::visit (AST::LifetimeParam &lifetime_param) -{} - -void -TopLevelScan::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -TopLevelScan::visit (AST::PathInExpression &path) -{ - auto it = functions.find (path.as_string ()); - bool foundFndecl = it != functions.end (); - if (foundFndecl) - { - fnLookup.push_back (it->second); - return; - } -} - -void -TopLevelScan::visit (AST::TypePathSegment &segment) -{} -void -TopLevelScan::visit (AST::TypePathSegmentGeneric &segment) -{} - -void -TopLevelScan::visit (AST::TypePathSegmentFunction &segment) -{} - -void -TopLevelScan::visit (AST::TypePath &path) -{} - -void -TopLevelScan::visit (AST::QualifiedPathInExpression &path) -{} - -void -TopLevelScan::visit (AST::QualifiedPathInType &path) -{} - -// rust-expr.h -void -TopLevelScan::visit (AST::LiteralExpr &expr) -{} - -void -TopLevelScan::visit (AST::AttrInputLiteral &attr_input) -{} - -void -TopLevelScan::visit (AST::MetaItemLitExpr &meta_item) -{} - -void -TopLevelScan::visit (AST::MetaItemPathLit &meta_item) -{} - -void -TopLevelScan::visit (AST::BorrowExpr &expr) -{} -void -TopLevelScan::visit (AST::DereferenceExpr &expr) -{} -void -TopLevelScan::visit (AST::ErrorPropagationExpr &expr) -{} -void -TopLevelScan::visit (AST::NegationExpr &expr) -{} - -void -TopLevelScan::visit (AST::ArithmeticOrLogicalExpr &expr) -{} - -void -TopLevelScan::visit (AST::ComparisonExpr &expr) -{} - -void -TopLevelScan::visit (AST::LazyBooleanExpr &expr) -{} - -void -TopLevelScan::visit (AST::TypeCastExpr &expr) -{} - -void -TopLevelScan::visit (AST::AssignmentExpr &expr) -{} - -void -TopLevelScan::visit (AST::CompoundAssignmentExpr &expr) -{} - -void -TopLevelScan::visit (AST::GroupedExpr &expr) -{} -// void TopLevelScan::visit(ArrayElems& elems) {} -void -TopLevelScan::visit (AST::ArrayElemsValues &elems) -{} -void -TopLevelScan::visit (AST::ArrayElemsCopied &elems) -{} -void -TopLevelScan::visit (AST::ArrayExpr &expr) -{} -void -TopLevelScan::visit (AST::ArrayIndexExpr &expr) -{} -void -TopLevelScan::visit (AST::TupleExpr &expr) -{} -void -TopLevelScan::visit (AST::TupleIndexExpr &expr) -{} -void -TopLevelScan::visit (AST::StructExprStruct &expr) -{} -// void TopLevelScan::visit(StructExprField& field) {} -void -TopLevelScan::visit (AST::StructExprFieldIdentifier &field) -{} -void -TopLevelScan::visit (AST::StructExprFieldIdentifierValue &field) -{} -void -TopLevelScan::visit (AST::StructExprFieldIndexValue &field) -{} -void -TopLevelScan::visit (AST::StructExprStructFields &expr) -{} -void -TopLevelScan::visit (AST::StructExprStructBase &expr) -{} -void -TopLevelScan::visit (AST::StructExprTuple &expr) -{} -void -TopLevelScan::visit (AST::StructExprUnit &expr) -{} -// void TopLevelScan::visit(EnumExprField& field) {} -void -TopLevelScan::visit (AST::EnumExprFieldIdentifier &field) -{} -void -TopLevelScan::visit (AST::EnumExprFieldIdentifierValue &field) -{} -void -TopLevelScan::visit (AST::EnumExprFieldIndexValue &field) -{} -void -TopLevelScan::visit (AST::EnumExprStruct &expr) -{} -void -TopLevelScan::visit (AST::EnumExprTuple &expr) -{} -void -TopLevelScan::visit (AST::EnumExprFieldless &expr) -{} - -void -TopLevelScan::visit (AST::CallExpr &expr) -{} - -void -TopLevelScan::visit (AST::MethodCallExpr &expr) -{} -void -TopLevelScan::visit (AST::FieldAccessExpr &expr) -{} -void -TopLevelScan::visit (AST::ClosureExprInner &expr) -{} -void -TopLevelScan::visit (AST::BlockExpr &expr) -{} -void -TopLevelScan::visit (AST::ClosureExprInnerTyped &expr) -{} -void -TopLevelScan::visit (AST::ContinueExpr &expr) -{} -void -TopLevelScan::visit (AST::BreakExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeFromToExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeFromExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeToExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeFullExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeFromToInclExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeToInclExpr &expr) -{} -void -TopLevelScan::visit (AST::ReturnExpr &expr) -{} -void -TopLevelScan::visit (AST::UnsafeBlockExpr &expr) -{} -void -TopLevelScan::visit (AST::LoopExpr &expr) -{} -void -TopLevelScan::visit (AST::WhileLoopExpr &expr) -{} -void -TopLevelScan::visit (AST::WhileLetLoopExpr &expr) -{} -void -TopLevelScan::visit (AST::ForLoopExpr &expr) -{} -void -TopLevelScan::visit (AST::IfExpr &expr) -{} -void -TopLevelScan::visit (AST::IfExprConseqElse &expr) -{} -void -TopLevelScan::visit (AST::IfExprConseqIf &expr) -{} -void -TopLevelScan::visit (AST::IfExprConseqIfLet &expr) -{} -void -TopLevelScan::visit (AST::IfLetExpr &expr) -{} -void -TopLevelScan::visit (AST::IfLetExprConseqElse &expr) -{} -void -TopLevelScan::visit (AST::IfLetExprConseqIf &expr) -{} -void -TopLevelScan::visit (AST::IfLetExprConseqIfLet &expr) -{} -// void TopLevelScan::visit(MatchCase& match_case) {} -/*void -TopLevelScan::visit (AST::MatchCaseBlockExpr &match_case) -{}*/ -/*void -TopLevelScan::visit (AST::MatchCaseExpr &match_case) -{}*/ -void -TopLevelScan::visit (AST::MatchExpr &expr) -{} -void -TopLevelScan::visit (AST::AwaitExpr &expr) -{} -void -TopLevelScan::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -TopLevelScan::visit (AST::TypeParam ¶m) -{} -// void TopLevelScan::visit(WhereClauseItem& item) {} -void -TopLevelScan::visit (AST::LifetimeWhereClauseItem &item) -{} -void -TopLevelScan::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -TopLevelScan::visit (AST::Method &method) -{} -void -TopLevelScan::visit (AST::ModuleBodied &module) -{} -void -TopLevelScan::visit (AST::ModuleNoBody &module) -{} -void -TopLevelScan::visit (AST::ExternCrate &crate) -{} -// void TopLevelScan::visit(UseTree& use_tree) {} -void -TopLevelScan::visit (AST::UseTreeGlob &use_tree) -{} -void -TopLevelScan::visit (AST::UseTreeList &use_tree) -{} -void -TopLevelScan::visit (AST::UseTreeRebind &use_tree) -{} -void -TopLevelScan::visit (AST::UseDeclaration &use_decl) -{} - -void -TopLevelScan::visit (AST::Function &function) -{ - functions[function.get_function_name ()] = &function; -} - -void -TopLevelScan::visit (AST::TypeAlias &type_alias) -{} -void -TopLevelScan::visit (AST::StructStruct &struct_item) -{} -void -TopLevelScan::visit (AST::TupleStruct &tuple_struct) -{} -void -TopLevelScan::visit (AST::EnumItem &item) -{} -void -TopLevelScan::visit (AST::EnumItemTuple &item) -{} -void -TopLevelScan::visit (AST::EnumItemStruct &item) -{} -void -TopLevelScan::visit (AST::EnumItemDiscriminant &item) -{} -void -TopLevelScan::visit (AST::Enum &enum_item) -{} -void -TopLevelScan::visit (AST::Union &union_item) -{} - -void -TopLevelScan::visit (AST::ConstantItem &const_item) -{} - -void -TopLevelScan::visit (AST::StaticItem &static_item) -{} -void -TopLevelScan::visit (AST::TraitItemFunc &item) -{} -void -TopLevelScan::visit (AST::TraitItemMethod &item) -{} -void -TopLevelScan::visit (AST::TraitItemConst &item) -{} -void -TopLevelScan::visit (AST::TraitItemType &item) -{} -void -TopLevelScan::visit (AST::Trait &trait) -{} -void -TopLevelScan::visit (AST::InherentImpl &impl) -{} -void -TopLevelScan::visit (AST::TraitImpl &impl) -{} -// void TopLevelScan::visit(ExternalItem& item) {} -void -TopLevelScan::visit (AST::ExternalStaticItem &item) -{} -void -TopLevelScan::visit (AST::ExternalFunctionItem &item) -{} -void -TopLevelScan::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -TopLevelScan::visit (AST::MacroMatchFragment &match) -{} -void -TopLevelScan::visit (AST::MacroMatchRepetition &match) -{} -void -TopLevelScan::visit (AST::MacroMatcher &matcher) -{} -void -TopLevelScan::visit (AST::MacroRulesDefinition &rules_def) -{} -void -TopLevelScan::visit (AST::MacroInvocation ¯o_invoc) -{} -void -TopLevelScan::visit (AST::MetaItemPath &meta_item) -{} -void -TopLevelScan::visit (AST::MetaItemSeq &meta_item) -{} -void -TopLevelScan::visit (AST::MetaWord &meta_item) -{} -void -TopLevelScan::visit (AST::MetaNameValueStr &meta_item) -{} -void -TopLevelScan::visit (AST::MetaListPaths &meta_item) -{} -void -TopLevelScan::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -TopLevelScan::visit (AST::LiteralPattern &pattern) -{} - -void -TopLevelScan::visit (AST::IdentifierPattern &pattern) -{} - -void -TopLevelScan::visit (AST::WildcardPattern &pattern) -{} -// void TopLevelScan::visit(RangePatternBound& bound) {} -void -TopLevelScan::visit (AST::RangePatternBoundLiteral &bound) -{} -void -TopLevelScan::visit (AST::RangePatternBoundPath &bound) -{} -void -TopLevelScan::visit (AST::RangePatternBoundQualPath &bound) -{} -void -TopLevelScan::visit (AST::RangePattern &pattern) -{} -void -TopLevelScan::visit (AST::ReferencePattern &pattern) -{} -// void TopLevelScan::visit(StructPatternField& field) {} -void -TopLevelScan::visit (AST::StructPatternFieldTuplePat &field) -{} -void -TopLevelScan::visit (AST::StructPatternFieldIdentPat &field) -{} -void -TopLevelScan::visit (AST::StructPatternFieldIdent &field) -{} -void -TopLevelScan::visit (AST::StructPattern &pattern) -{} -// void TopLevelScan::visit(TupleStructItems& tuple_items) {} -void -TopLevelScan::visit (AST::TupleStructItemsNoRange &tuple_items) -{} -void -TopLevelScan::visit (AST::TupleStructItemsRange &tuple_items) -{} -void -TopLevelScan::visit (AST::TupleStructPattern &pattern) -{} -// void TopLevelScan::visit(TuplePatternItems& tuple_items) {} -void -TopLevelScan::visit (AST::TuplePatternItemsMultiple &tuple_items) -{} -void -TopLevelScan::visit (AST::TuplePatternItemsRanged &tuple_items) -{} -void -TopLevelScan::visit (AST::TuplePattern &pattern) -{} -void -TopLevelScan::visit (AST::GroupedPattern &pattern) -{} -void -TopLevelScan::visit (AST::SlicePattern &pattern) -{} - -// rust-stmt.h -void -TopLevelScan::visit (AST::EmptyStmt &stmt) -{} - -void -TopLevelScan::visit (AST::LetStmt &stmt) -{} - -void -TopLevelScan::visit (AST::ExprStmtWithoutBlock &stmt) -{} - -void -TopLevelScan::visit (AST::ExprStmtWithBlock &stmt) -{} - -// rust-type.h -void -TopLevelScan::visit (AST::TraitBound &bound) -{} - -void -TopLevelScan::visit (AST::ImplTraitType &type) -{} - -void -TopLevelScan::visit (AST::TraitObjectType &type) -{} -void -TopLevelScan::visit (AST::ParenthesisedType &type) -{} -void -TopLevelScan::visit (AST::ImplTraitTypeOneBound &type) -{} -void -TopLevelScan::visit (AST::TraitObjectTypeOneBound &type) -{} -void -TopLevelScan::visit (AST::TupleType &type) -{} -void -TopLevelScan::visit (AST::NeverType &type) -{} -void -TopLevelScan::visit (AST::RawPointerType &type) -{} -void -TopLevelScan::visit (AST::ReferenceType &type) -{} -void -TopLevelScan::visit (AST::ArrayType &type) -{} -void -TopLevelScan::visit (AST::SliceType &type) -{} -void -TopLevelScan::visit (AST::InferredType &type) -{} -void -TopLevelScan::visit (AST::BareFunctionType &type) -{} - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-scan.h b/gcc/rust/analysis/rust-scan.h deleted file mode 100644 index 77beeca..0000000 --- a/gcc/rust/analysis/rust-scan.h +++ /dev/null @@ -1,233 +0,0 @@ -#pragma once - -#include "rust-system.h" -#include "rust-ast-full.h" -#include "rust-ast-visitor.h" -#include "scope.h" - -namespace Rust { -namespace Analysis { - -class TopLevelScan : public AST::ASTVisitor -{ -public: - TopLevelScan (AST::Crate &crate); - - ~TopLevelScan (); - - AST::Function *lookupFunction (AST::Expr *expr); - - // visitor impl - // rust-ast.h - // virtual void visit(AttrInput& attr_input); - // virtual void visit(TokenTree& token_tree); - // virtual void visit(MacroMatch& macro_match); - virtual void visit (AST::Token &tok); - virtual void visit (AST::DelimTokenTree &delim_tok_tree); - virtual void visit (AST::AttrInputMetaItemContainer &input); - // virtual void visit(MetaItem& meta_item); - // virtual void vsit(Stmt& stmt); - // virtual void visit(Expr& expr); - virtual void visit (AST::IdentifierExpr &ident_expr); - // virtual void visit(Pattern& pattern); - // virtual void visit(Type& type); - // virtual void visit(TypeParamBound& type_param_bound); - virtual void visit (AST::Lifetime &lifetime); - // virtual void visit(GenericParam& generic_param); - virtual void visit (AST::LifetimeParam &lifetime_param); - // virtual void visit(TraitItem& trait_item); - // virtual void visit(InherentImplItem& inherent_impl_item); - // virtual void visit(TraitImplItem& trait_impl_item); - virtual void visit (AST::MacroInvocationSemi ¯o); - - // rust-path.h - virtual void visit (AST::PathInExpression &path); - virtual void visit (AST::TypePathSegment &segment); - virtual void visit (AST::TypePathSegmentGeneric &segment); - virtual void visit (AST::TypePathSegmentFunction &segment); - virtual void visit (AST::TypePath &path); - virtual void visit (AST::QualifiedPathInExpression &path); - virtual void visit (AST::QualifiedPathInType &path); - - // rust-expr.h - virtual void visit (AST::LiteralExpr &expr); - virtual void visit (AST::AttrInputLiteral &attr_input); - virtual void visit (AST::MetaItemLitExpr &meta_item); - virtual void visit (AST::MetaItemPathLit &meta_item); - virtual void visit (AST::BorrowExpr &expr); - virtual void visit (AST::DereferenceExpr &expr); - virtual void visit (AST::ErrorPropagationExpr &expr); - virtual void visit (AST::NegationExpr &expr); - virtual void visit (AST::ArithmeticOrLogicalExpr &expr); - virtual void visit (AST::ComparisonExpr &expr); - virtual void visit (AST::LazyBooleanExpr &expr); - virtual void visit (AST::TypeCastExpr &expr); - virtual void visit (AST::AssignmentExpr &expr); - virtual void visit (AST::CompoundAssignmentExpr &expr); - virtual void visit (AST::GroupedExpr &expr); - // virtual void visit(ArrayElems& elems); - virtual void visit (AST::ArrayElemsValues &elems); - virtual void visit (AST::ArrayElemsCopied &elems); - virtual void visit (AST::ArrayExpr &expr); - virtual void visit (AST::ArrayIndexExpr &expr); - virtual void visit (AST::TupleExpr &expr); - virtual void visit (AST::TupleIndexExpr &expr); - virtual void visit (AST::StructExprStruct &expr); - // virtual void visit(StructExprField& field); - virtual void visit (AST::StructExprFieldIdentifier &field); - virtual void visit (AST::StructExprFieldIdentifierValue &field); - virtual void visit (AST::StructExprFieldIndexValue &field); - virtual void visit (AST::StructExprStructFields &expr); - virtual void visit (AST::StructExprStructBase &expr); - virtual void visit (AST::StructExprTuple &expr); - virtual void visit (AST::StructExprUnit &expr); - // virtual void visit(EnumExprField& field); - virtual void visit (AST::EnumExprFieldIdentifier &field); - virtual void visit (AST::EnumExprFieldIdentifierValue &field); - virtual void visit (AST::EnumExprFieldIndexValue &field); - virtual void visit (AST::EnumExprStruct &expr); - virtual void visit (AST::EnumExprTuple &expr); - virtual void visit (AST::EnumExprFieldless &expr); - virtual void visit (AST::CallExpr &expr); - virtual void visit (AST::MethodCallExpr &expr); - virtual void visit (AST::FieldAccessExpr &expr); - virtual void visit (AST::ClosureExprInner &expr); - virtual void visit (AST::BlockExpr &expr); - virtual void visit (AST::ClosureExprInnerTyped &expr); - virtual void visit (AST::ContinueExpr &expr); - virtual void visit (AST::BreakExpr &expr); - virtual void visit (AST::RangeFromToExpr &expr); - virtual void visit (AST::RangeFromExpr &expr); - virtual void visit (AST::RangeToExpr &expr); - virtual void visit (AST::RangeFullExpr &expr); - virtual void visit (AST::RangeFromToInclExpr &expr); - virtual void visit (AST::RangeToInclExpr &expr); - virtual void visit (AST::ReturnExpr &expr); - virtual void visit (AST::UnsafeBlockExpr &expr); - virtual void visit (AST::LoopExpr &expr); - virtual void visit (AST::WhileLoopExpr &expr); - virtual void visit (AST::WhileLetLoopExpr &expr); - virtual void visit (AST::ForLoopExpr &expr); - virtual void visit (AST::IfExpr &expr); - virtual void visit (AST::IfExprConseqElse &expr); - virtual void visit (AST::IfExprConseqIf &expr); - virtual void visit (AST::IfExprConseqIfLet &expr); - virtual void visit (AST::IfLetExpr &expr); - virtual void visit (AST::IfLetExprConseqElse &expr); - virtual void visit (AST::IfLetExprConseqIf &expr); - virtual void visit (AST::IfLetExprConseqIfLet &expr); - // virtual void visit(MatchCase& match_case); - // virtual void visit (AST::MatchCaseBlockExpr &match_case); - // virtual void visit (AST::MatchCaseExpr &match_case); - virtual void visit (AST::MatchExpr &expr); - virtual void visit (AST::AwaitExpr &expr); - virtual void visit (AST::AsyncBlockExpr &expr); - - // rust-item.h - virtual void visit (AST::TypeParam ¶m); - // virtual void visit(WhereClauseItem& item); - virtual void visit (AST::LifetimeWhereClauseItem &item); - virtual void visit (AST::TypeBoundWhereClauseItem &item); - virtual void visit (AST::Method &method); - virtual void visit (AST::ModuleBodied &module); - virtual void visit (AST::ModuleNoBody &module); - virtual void visit (AST::ExternCrate &crate); - // virtual void visit(UseTree& use_tree); - virtual void visit (AST::UseTreeGlob &use_tree); - virtual void visit (AST::UseTreeList &use_tree); - virtual void visit (AST::UseTreeRebind &use_tree); - virtual void visit (AST::UseDeclaration &use_decl); - virtual void visit (AST::Function &function); - virtual void visit (AST::TypeAlias &type_alias); - virtual void visit (AST::StructStruct &struct_item); - virtual void visit (AST::TupleStruct &tuple_struct); - virtual void visit (AST::EnumItem &item); - virtual void visit (AST::EnumItemTuple &item); - virtual void visit (AST::EnumItemStruct &item); - virtual void visit (AST::EnumItemDiscriminant &item); - virtual void visit (AST::Enum &enum_item); - virtual void visit (AST::Union &union_item); - virtual void visit (AST::ConstantItem &const_item); - virtual void visit (AST::StaticItem &static_item); - virtual void visit (AST::TraitItemFunc &item); - virtual void visit (AST::TraitItemMethod &item); - virtual void visit (AST::TraitItemConst &item); - virtual void visit (AST::TraitItemType &item); - virtual void visit (AST::Trait &trait); - virtual void visit (AST::InherentImpl &impl); - virtual void visit (AST::TraitImpl &impl); - // virtual void visit(ExternalItem& item); - virtual void visit (AST::ExternalStaticItem &item); - virtual void visit (AST::ExternalFunctionItem &item); - virtual void visit (AST::ExternBlock &block); - - // rust-macro.h - virtual void visit (AST::MacroMatchFragment &match); - virtual void visit (AST::MacroMatchRepetition &match); - virtual void visit (AST::MacroMatcher &matcher); - virtual void visit (AST::MacroRulesDefinition &rules_def); - virtual void visit (AST::MacroInvocation ¯o_invoc); - virtual void visit (AST::MetaItemPath &meta_item); - virtual void visit (AST::MetaItemSeq &meta_item); - virtual void visit (AST::MetaWord &meta_item); - virtual void visit (AST::MetaNameValueStr &meta_item); - virtual void visit (AST::MetaListPaths &meta_item); - virtual void visit (AST::MetaListNameValueStr &meta_item); - - // rust-pattern.h - virtual void visit (AST::LiteralPattern &pattern); - virtual void visit (AST::IdentifierPattern &pattern); - virtual void visit (AST::WildcardPattern &pattern); - // virtual void visit(RangePatternBound& bound); - virtual void visit (AST::RangePatternBoundLiteral &bound); - virtual void visit (AST::RangePatternBoundPath &bound); - virtual void visit (AST::RangePatternBoundQualPath &bound); - virtual void visit (AST::RangePattern &pattern); - virtual void visit (AST::ReferencePattern &pattern); - // virtual void visit(StructPatternField& field); - virtual void visit (AST::StructPatternFieldTuplePat &field); - virtual void visit (AST::StructPatternFieldIdentPat &field); - virtual void visit (AST::StructPatternFieldIdent &field); - virtual void visit (AST::StructPattern &pattern); - // virtual void visit(TupleStructItems& tuple_items); - virtual void visit (AST::TupleStructItemsNoRange &tuple_items); - virtual void visit (AST::TupleStructItemsRange &tuple_items); - virtual void visit (AST::TupleStructPattern &pattern); - // virtual void visit(TuplePatternItems& tuple_items); - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items); - virtual void visit (AST::TuplePatternItemsRanged &tuple_items); - virtual void visit (AST::TuplePattern &pattern); - virtual void visit (AST::GroupedPattern &pattern); - virtual void visit (AST::SlicePattern &pattern); - - // rust-stmt.h - virtual void visit (AST::EmptyStmt &stmt); - virtual void visit (AST::LetStmt &stmt); - virtual void visit (AST::ExprStmtWithoutBlock &stmt); - virtual void visit (AST::ExprStmtWithBlock &stmt); - - // rust-type.h - virtual void visit (AST::TraitBound &bound); - virtual void visit (AST::ImplTraitType &type); - virtual void visit (AST::TraitObjectType &type); - virtual void visit (AST::ParenthesisedType &type); - virtual void visit (AST::ImplTraitTypeOneBound &type); - virtual void visit (AST::TraitObjectTypeOneBound &type); - virtual void visit (AST::TupleType &type); - virtual void visit (AST::NeverType &type); - virtual void visit (AST::RawPointerType &type); - virtual void visit (AST::ReferenceType &type); - virtual void visit (AST::ArrayType &type); - virtual void visit (AST::SliceType &type); - virtual void visit (AST::InferredType &type); - virtual void visit (AST::BareFunctionType &type); - -private: - std::map<std::string, AST::Function *> functions; - AST::Crate &crate; - - std::vector<AST::Function *> fnLookup; -}; - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-type-resolution.cc b/gcc/rust/analysis/rust-type-resolution.cc deleted file mode 100644 index f1edec8..0000000 --- a/gcc/rust/analysis/rust-type-resolution.cc +++ /dev/null @@ -1,1348 +0,0 @@ -#include "rust-type-resolution.h" -#include "rust-diagnostics.h" -#include "rust-type-visitor.h" - -#define ADD_BUILTIN_TYPE(_X, _S) \ - do \ - { \ - AST::PathIdentSegment seg (_X); \ - auto typePath = ::std::unique_ptr<AST::TypePathSegment> ( \ - new AST::TypePathSegment (::std::move (seg), false, \ - Linemap::predeclared_location ())); \ - ::std::vector< ::std::unique_ptr<AST::TypePathSegment> > segs; \ - segs.push_back (::std::move (typePath)); \ - auto bType \ - = new AST::TypePath (::std::move (segs), \ - Linemap::predeclared_location (), false); \ - _S.InsertType (_X, bType); \ - } \ - while (0) - -namespace Rust { -namespace Analysis { - -TypeResolution::TypeResolution (AST::Crate &crate, TopLevelScan &toplevel) - : Resolution (crate, toplevel) -{ - scope.Push (); - - // push all builtin types - this is probably too basic for future needs - ADD_BUILTIN_TYPE ("u8", scope); - ADD_BUILTIN_TYPE ("u16", scope); - ADD_BUILTIN_TYPE ("u32", scope); - ADD_BUILTIN_TYPE ("u64", scope); - - ADD_BUILTIN_TYPE ("i8", scope); - ADD_BUILTIN_TYPE ("i16", scope); - ADD_BUILTIN_TYPE ("i32", scope); - ADD_BUILTIN_TYPE ("i64", scope); - - ADD_BUILTIN_TYPE ("f32", scope); - ADD_BUILTIN_TYPE ("f64", scope); - - ADD_BUILTIN_TYPE ("char", scope); - ADD_BUILTIN_TYPE ("str", scope); - ADD_BUILTIN_TYPE ("bool", scope); - - // now its the crate scope - scope.Push (); -} - -TypeResolution::~TypeResolution () -{ - scope.Pop (); // crate - scope.Pop (); // builtins -} - -bool -TypeResolution::Resolve (AST::Crate &crate, TopLevelScan &toplevel) -{ - TypeResolution resolver (crate, toplevel); - return resolver.go (); -} - -bool -TypeResolution::go () -{ - for (auto &item : crate.items) - item->accept_vis (*this); - - return true; -} - -bool -TypeResolution::typesAreCompatible (AST::Type *lhs, AST::Type *rhs, - Location locus) -{ - auto before = typeComparisonBuffer.size (); - lhs->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (locus, "failed to understand type for lhs"); - return false; - } - - auto lhsTypeStr = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - rhs->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (locus, "failed to understand type for rhs"); - return false; - } - - auto rhsTypeStr = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - // FIXME this needs to handle the cases of an i8 going into an i32 which is - // compatible - if (lhsTypeStr.compare (rhsTypeStr)) - { - rust_error_at (locus, "E0308: expected: %s, found %s", - lhsTypeStr.c_str (), rhsTypeStr.c_str ()); - return false; - } - - AST::Type *val = NULL; - if (!scope.LookupType (lhsTypeStr, &val)) - { - rust_error_at (locus, "Unknown type: %s", lhsTypeStr.c_str ()); - return false; - } - - return true; -} - -bool -TypeResolution::isTypeInScope (AST::Type *type, Location locus) -{ - auto before = typeComparisonBuffer.size (); - type->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (locus, "unable to decipher type: %s", - type->as_string ().c_str ()); - return false; - } - - auto t = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - AST::Type *val = NULL; - return scope.LookupType (t, &val); -} - -AST::Function * -TypeResolution::lookupFndecl (AST::Expr *expr) -{ - size_t before = functionLookup.size (); - expr->accept_vis (*this); - if (functionLookup.size () > before) - { - auto fndecl = functionLookup.back (); - functionLookup.pop_back (); - return fndecl; - } - - rust_error_at (expr->get_locus_slow (), "failed to lookup function"); - return NULL; -} - -void -TypeResolution::visit (AST::Token &tok) -{} - -void -TypeResolution::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -TypeResolution::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -TypeResolution::visit (AST::IdentifierExpr &ident_expr) -{ - AST::Type *type = NULL; - bool ok = scope.LookupType (ident_expr.get_ident (), &type); - if (!ok) - { - rust_error_at (ident_expr.get_locus (), "unknown identifier"); - return; - } - - typeBuffer.push_back (type); -} - -void -TypeResolution::visit (AST::Lifetime &lifetime) -{} - -void -TypeResolution::visit (AST::LifetimeParam &lifetime_param) -{} - -void -TypeResolution::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -TypeResolution::visit (AST::PathInExpression &path) -{ - // look up in the functionScope else lookup in the toplevel scan - AST::Function *fndecl = NULL; - if (scope.LookupFunction (path.as_string (), &fndecl)) - { - functionLookup.push_back (fndecl); - return; - } - - fndecl = toplevel.lookupFunction (&path); - if (fndecl != NULL) - { - functionLookup.push_back (fndecl); - return; - } -} - -void -TypeResolution::visit (AST::TypePathSegment &segment) -{} -void -TypeResolution::visit (AST::TypePathSegmentGeneric &segment) -{} - -void -TypeResolution::visit (AST::TypePathSegmentFunction &segment) -{} - -void -TypeResolution::visit (AST::TypePath &path) -{ - // this may not be robust enough for type comparisons but lets try it for now - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -TypeResolution::visit (AST::QualifiedPathInExpression &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -TypeResolution::visit (AST::QualifiedPathInType &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -// rust-expr.h -void -TypeResolution::visit (AST::LiteralExpr &expr) -{ - std::string type; - switch (expr.get_lit_type ()) - { - case AST::Literal::CHAR: - type = "char"; - break; - - case AST::Literal::STRING: - case AST::Literal::RAW_STRING: - type = "str"; - break; - - case AST::Literal::BOOL: - type = "bool"; - break; - - case AST::Literal::BYTE: - type = "u8"; - break; - - // FIXME these are not always going to be the case - // eg: suffix on the value can change the type - case AST::Literal::FLOAT: - type = "f32"; - break; - - case AST::Literal::INT: - type = "i32"; - break; - - case AST::Literal::BYTE_STRING: - case AST::Literal::RAW_BYTE_STRING: - // FIXME - break; - } - - if (type.empty ()) - { - rust_error_at (expr.get_locus (), "unknown literal: %s", - expr.get_literal ().as_string ().c_str ()); - return; - } - - AST::Type *val = NULL; - bool ok = scope.LookupType (type, &val); - if (ok) - typeBuffer.push_back (val); - else - rust_error_at (expr.get_locus (), "unknown literal type: %s", type.c_str ()); -} - -void -TypeResolution::visit (AST::AttrInputLiteral &attr_input) -{} - -void -TypeResolution::visit (AST::MetaItemLitExpr &meta_item) -{} - -void -TypeResolution::visit (AST::MetaItemPathLit &meta_item) -{} - -void -TypeResolution::visit (AST::BorrowExpr &expr) -{} -void -TypeResolution::visit (AST::DereferenceExpr &expr) -{} -void -TypeResolution::visit (AST::ErrorPropagationExpr &expr) -{} -void -TypeResolution::visit (AST::NegationExpr &expr) -{} - -void -TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - size_t before; - before = typeBuffer.size (); - expr.visit_lhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus (), "unable to determine lhs type"); - return; - } - - auto lhsType = typeBuffer.back (); - typeBuffer.pop_back (); - - before = typeBuffer.size (); - expr.visit_rhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus (), "unable to determine rhs type"); - return; - } - - auto rhsType = typeBuffer.back (); - // not poping because we will be checking they match and the - // scope will require knowledge of the type - - // do the lhsType and the rhsType match - typesAreCompatible (lhsType, rhsType, expr.get_right_expr ()->get_locus_slow ()); -} - -void -TypeResolution::visit (AST::ComparisonExpr &expr) -{} - -void -TypeResolution::visit (AST::LazyBooleanExpr &expr) -{} - -void -TypeResolution::visit (AST::TypeCastExpr &expr) -{} - -void -TypeResolution::visit (AST::AssignmentExpr &expr) -{ - size_t before; - before = typeBuffer.size (); - expr.visit_lhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus (), "unable to determine lhs type"); - return; - } - - auto lhsType = typeBuffer.back (); - typeBuffer.pop_back (); - - before = typeBuffer.size (); - expr.visit_rhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus (), "unable to determine rhs type"); - return; - } - - auto rhsType = typeBuffer.back (); - // not poping because we will be checking they match and the - // scope will require knowledge of the type - - // do the lhsType and the rhsType match - if (!typesAreCompatible (lhsType, rhsType, - expr.get_right_expr ()->get_locus_slow ())) - return; - - // is the lhs mutable? -} - -void -TypeResolution::visit (AST::CompoundAssignmentExpr &expr) -{} - -void -TypeResolution::visit (AST::GroupedExpr &expr) -{} - -void -TypeResolution::visit (AST::ArrayElemsValues &elems) -{ - // we need to generate the AST::ArrayType for this array init_expression - // we can get the size via get_num_values() but we need to ensure each element - // are type compatible - - bool failed = false; - AST::Type *last_inferred_type = nullptr; - elems.iterate ([&] (AST::Expr *expr) mutable -> bool { - size_t before; - before = typeBuffer.size (); - expr->accept_vis (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr->get_locus_slow (), - "unable to determine element type"); - return false; - } - - AST::Type *inferedType = typeBuffer.back (); - typeBuffer.pop_back (); - - if (last_inferred_type == nullptr) - last_inferred_type = inferedType; - else - { - if (!typesAreCompatible (last_inferred_type, inferedType, - expr->get_locus_slow ())) - { - failed = true; - return false; - } - } - - return true; - }); - - // nothing to do when its failed - if (failed) - return; - - // FIXME This will leak - auto capacity - = new AST::LiteralExpr (std::to_string (elems.get_num_values ()), - AST::Literal::INT, - Linemap::predeclared_location ()); - auto arrayType = new AST::ArrayType (last_inferred_type->clone_type (), - std::unique_ptr<AST::Expr> (capacity), - Linemap::predeclared_location ()); - typeBuffer.push_back (arrayType); -} - -void -TypeResolution::visit (AST::ArrayElemsCopied &elems) -{ - printf ("ArrayElemsCopied: %s\n", elems.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::ArrayExpr &expr) -{ - auto& elements = expr.get_array_elems (); - - auto before = typeBuffer.size (); - elements->accept_vis (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus_slow (), - "unable to determine type for ArrayExpr"); - return; - } - - expr.set_inferred_type (typeBuffer.back ()); -} - -void -TypeResolution::visit (AST::ArrayIndexExpr &expr) -{ - auto before = typeBuffer.size (); - expr.get_array_expr ()->accept_vis (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus_slow (), - "unable to determine type for array index expression"); - return; - } - AST::Type *array_expr_type = typeBuffer.back (); - typeBuffer.pop_back (); - - before = typeBuffer.size (); - expr.get_index_expr ()->accept_vis (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_index_expr ()->get_locus_slow (), - "unable to determine type for index expression"); - return; - } - - AST::Type *array_index_type = typeBuffer.back (); - typeBuffer.pop_back (); - - // check the index_type should be an i32 which should really be - // more permissive - AST::Type *i32 = nullptr; - scope.LookupType ("i32", &i32); - rust_assert (i32 != nullptr); - - if (!typesAreCompatible (array_index_type, i32, - expr.get_index_expr ()->get_locus_slow ())) - { - return; - } - - // the the element type from the array_expr_type and it _must_ be an array - AST::ArrayType *resolved = ArrayTypeVisitor::Resolve (array_expr_type); - if (resolved == nullptr) - { - rust_error_at (expr.get_locus_slow (), - "unable to resolve type for array expression"); - return; - } - - typeBuffer.push_back (resolved->get_elem_type ().get ()); -} - -void -TypeResolution::visit (AST::TupleExpr &expr) -{} -void -TypeResolution::visit (AST::TupleIndexExpr &expr) -{} - -void -TypeResolution::visit (AST::StructExprStruct &expr) -{} - -// void TypeResolution::visit(StructExprField& field) {} -void -TypeResolution::visit (AST::StructExprFieldIdentifier &field) -{} - -void -TypeResolution::visit (AST::StructExprFieldIdentifierValue &field) -{ - identifierBuffer = std::unique_ptr<std::string> (new std::string (field.get_field_name ())); - field.get_value ()->accept_vis (*this); -} - -void -TypeResolution::visit (AST::StructExprFieldIndexValue &field) -{ - tupleIndexBuffer = std::unique_ptr<int> (new int (field.get_index ())); - field.get_value ()->accept_vis (*this); -} - -void -TypeResolution::visit (AST::StructExprStructFields &expr) -{ - AST::StructStruct *decl = NULL; - if (!scope.LookupStruct (expr.get_struct_name ().as_string (), &decl)) - { - rust_error_at (expr.get_locus_slow (), "unknown type"); - return; - } - - for (auto &field : expr.get_fields ()) - { - identifierBuffer = NULL; - tupleIndexBuffer = NULL; - - auto before = typeBuffer.size (); - field->accept_vis (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus_slow (), - "unable to determine type for field"); - return; - } - - auto inferedType = typeBuffer.back (); - typeBuffer.pop_back (); - - // do we have a name for this - if (identifierBuffer != NULL) - { - AST::StructField *declField = NULL; - for (auto &df : decl->get_fields ()) - { - if (identifierBuffer->compare (df.get_field_name ()) == 0) - { - declField = &df; - break; - } - } - identifierBuffer = NULL; - - if (declField == NULL) - { - rust_error_at (expr.get_locus_slow (), "unknown field"); - return; - } - - if (!typesAreCompatible (declField->get_field_type ().get (), inferedType, - expr.get_locus_slow ())) - return; - } - // do we have an index for this - else if (tupleIndexBuffer != NULL) - { - AST::StructField *declField = NULL; - if (*tupleIndexBuffer < decl->get_fields ().size ()) - { - declField = &decl->get_fields ()[*tupleIndexBuffer]; - } - tupleIndexBuffer = NULL; - - if (declField == NULL) - { - rust_error_at (expr.get_locus_slow (), "unknown field at index"); - return; - } - - if (!typesAreCompatible (declField->get_field_type ().get (), inferedType, - expr.get_locus_slow ())) - return; - } - else - { - rust_fatal_error (expr.get_locus_slow (), "unknown field initialise"); - return; - } - } - - // need to correct the ordering with the respect to the struct definition and - // ensure we handle missing values and give them defaults - // FIXME - - // setup a path in type - AST::PathIdentSegment seg (expr.get_struct_name ().as_string ()); - auto typePath = ::std::unique_ptr<AST::TypePathSegment> ( - new AST::TypePathSegment (::std::move (seg), false, - expr.get_locus_slow ())); - ::std::vector< ::std::unique_ptr<AST::TypePathSegment> > segs; - segs.push_back (::std::move (typePath)); - auto bType - = new AST::TypePath (::std::move (segs), expr.get_locus_slow (), false); - typeBuffer.push_back (bType); -} - -void -TypeResolution::visit (AST::StructExprStructBase &expr) -{} -void -TypeResolution::visit (AST::StructExprTuple &expr) -{} -void -TypeResolution::visit (AST::StructExprUnit &expr) -{} -// void TypeResolution::visit(EnumExprField& field) {} -void -TypeResolution::visit (AST::EnumExprFieldIdentifier &field) -{} -void -TypeResolution::visit (AST::EnumExprFieldIdentifierValue &field) -{} -void -TypeResolution::visit (AST::EnumExprFieldIndexValue &field) -{} -void -TypeResolution::visit (AST::EnumExprStruct &expr) -{} -void -TypeResolution::visit (AST::EnumExprTuple &expr) -{} -void -TypeResolution::visit (AST::EnumExprFieldless &expr) -{} - -void -TypeResolution::visit (AST::CallExpr &expr) -{ - // this look up should probably be moved to name resolution - auto fndecl = lookupFndecl (expr.get_function_expr ().get ()); - if (fndecl == NULL) - return; - - // check num args match - if (fndecl->get_function_params ().size () != expr.get_params ().size ()) - { - rust_error_at (expr.get_locus_slow (), - "differing number of arguments vs parameters to function"); - return; - } - - typeBuffer.push_back (fndecl->get_return_type ().get ()); - expr.fndeclRef = fndecl; - - auto before = typeBuffer.size (); - for (auto &item : expr.get_params ()) - item->accept_vis (*this); - - auto numInferedParams = typeBuffer.size () - before; - if (numInferedParams != expr.get_params ().size ()) - { - rust_error_at (expr.get_locus (), "Failed to infer all parameters"); - return; - } - - auto offs = numInferedParams - 1; - for (auto it = fndecl->get_function_params ().rbegin (); - it != fndecl->get_function_params ().rend (); ++it) - { - AST::Type *argument = typeBuffer.back (); - typeBuffer.pop_back (); - - if (!typesAreCompatible (it->get_type ().get (), argument, - expr.get_params ()[offs]->get_locus_slow ())) - return; - offs--; - } -} - -void -TypeResolution::visit (AST::MethodCallExpr &expr) -{} -void -TypeResolution::visit (AST::FieldAccessExpr &expr) -{} -void -TypeResolution::visit (AST::ClosureExprInner &expr) -{} - -void -TypeResolution::visit (AST::BlockExpr &expr) -{ - scope.Push (); - for (auto &stmt : expr.get_statements ()) - { - stmt->accept_vis (*this); - } - scope.Pop (); -} - -void -TypeResolution::visit (AST::ClosureExprInnerTyped &expr) -{} -void -TypeResolution::visit (AST::ContinueExpr &expr) -{} -void -TypeResolution::visit (AST::BreakExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromToExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromExpr &expr) -{} -void -TypeResolution::visit (AST::RangeToExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFullExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromToInclExpr &expr) -{} -void -TypeResolution::visit (AST::RangeToInclExpr &expr) -{} - -void -TypeResolution::visit (AST::ReturnExpr &expr) -{ - // Ensure the type of this matches the function - auto before = typeBuffer.size (); - expr.get_returned_expr ()->accept_vis (*this); - - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_returned_expr ()->get_locus_slow (), - "unable to determine type for return expr"); - return; - } - - auto inferedType = typeBuffer.back (); - typeBuffer.pop_back (); - - // check this is compatible with the return type - // this will again have issues with structs before we move to HIR - - auto function = scope.CurrentFunction (); - if (!function->has_return_type ()) - { - rust_error_at (expr.get_locus (), "return for void function %s", - function->as_string ().c_str ()); - return; - } - - if (!typesAreCompatible (function->get_return_type ().get (), inferedType, - expr.get_locus_slow ())) - { - return; - } -} - -void -TypeResolution::visit (AST::UnsafeBlockExpr &expr) -{} -void -TypeResolution::visit (AST::LoopExpr &expr) -{} -void -TypeResolution::visit (AST::WhileLoopExpr &expr) -{} -void -TypeResolution::visit (AST::WhileLetLoopExpr &expr) -{} -void -TypeResolution::visit (AST::ForLoopExpr &expr) -{} - -void -TypeResolution::visit (AST::IfExpr &expr) -{ - expr.vis_if_block (*this); -} - -void -TypeResolution::visit (AST::IfExprConseqElse &expr) -{ - expr.vis_if_block (*this); - expr.vis_else_block (*this); -} - -void -TypeResolution::visit (AST::IfExprConseqIf &expr) -{ - expr.vis_if_block (*this); - expr.vis_conseq_if_expr (*this); -} - -void -TypeResolution::visit (AST::IfExprConseqIfLet &expr) -{} -void -TypeResolution::visit (AST::IfLetExpr &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqElse &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqIf &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqIfLet &expr) -{} -// void TypeResolution::visit(MatchCase& match_case) {} -/*void -TypeResolution::visit (AST::MatchCaseBlockExpr &match_case) -{}*/ -/*void -TypeResolution::visit (AST::MatchCaseExpr &match_case) -{}*/ -void -TypeResolution::visit (AST::MatchExpr &expr) -{} -void -TypeResolution::visit (AST::AwaitExpr &expr) -{} -void -TypeResolution::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -TypeResolution::visit (AST::TypeParam ¶m) -{} -// void TypeResolution::visit(WhereClauseItem& item) {} -void -TypeResolution::visit (AST::LifetimeWhereClauseItem &item) -{} -void -TypeResolution::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -TypeResolution::visit (AST::Method &method) -{} -void -TypeResolution::visit (AST::ModuleBodied &module) -{} -void -TypeResolution::visit (AST::ModuleNoBody &module) -{} -void -TypeResolution::visit (AST::ExternCrate &crate) -{} -// void TypeResolution::visit(UseTree& use_tree) {} -void -TypeResolution::visit (AST::UseTreeGlob &use_tree) -{} -void -TypeResolution::visit (AST::UseTreeList &use_tree) -{} -void -TypeResolution::visit (AST::UseTreeRebind &use_tree) -{} -void -TypeResolution::visit (AST::UseDeclaration &use_decl) -{} - -void -TypeResolution::visit (AST::Function &function) -{ - // always emit the function with return type in the event of nil return type - // its a marker for a void function - scope.InsertType (function.get_function_name (), function.get_return_type ().get ()); - scope.InsertFunction (function.get_function_name (), &function); - scope.PushFunction (&function); - scope.Push (); - - for (auto ¶m : function.get_function_params ()) - { - if (!isTypeInScope (param.get_type ().get (), param.get_locus ())) - { - scope.Pop (); - scope.PopFunction (); - return; - } - - auto before = letPatternBuffer.size (); - param.get_pattern ()->accept_vis (*this); - if (letPatternBuffer.size () <= before) - { - rust_error_at (param.get_locus (), "failed to analyse parameter name"); - - scope.Pop (); - scope.PopFunction (); - return; - } - - auto paramName = letPatternBuffer.back (); - letPatternBuffer.pop_back (); - scope.InsertType (paramName.get_ident (), param.get_type ().get ()); - } - - // ensure the return type is resolved - if (function.has_return_type ()) - { - if (!isTypeInScope (function.get_return_type ().get (), function.get_locus ())) - { - scope.Pop (); - scope.PopFunction (); - return; - } - } - - // walk the expression body - for (auto &stmt : function.get_definition ()->get_statements ()) - { - stmt->accept_vis (*this); - } - - auto localMap = scope.PeekLocals (); - for (auto &[_, value] : localMap) - function.locals.push_back (value); - - scope.Pop (); - scope.PopFunction (); -} - -void -TypeResolution::visit (AST::TypeAlias &type_alias) -{} - -void -TypeResolution::visit (AST::StructStruct &struct_item) -{ - for (auto &field : struct_item.get_fields ()) - { - if (!isTypeInScope (field.get_field_type ().get (), - Linemap::unknown_location ())) - { - rust_fatal_error (Linemap::unknown_location (), - "unknown type in struct field"); - return; - } - } - - scope.InsertStruct (struct_item.get_struct_name (), &struct_item); -} - -void -TypeResolution::visit (AST::TupleStruct &tuple_struct) -{} -void -TypeResolution::visit (AST::EnumItem &item) -{} -void -TypeResolution::visit (AST::EnumItemTuple &item) -{} -void -TypeResolution::visit (AST::EnumItemStruct &item) -{} -void -TypeResolution::visit (AST::EnumItemDiscriminant &item) -{} -void -TypeResolution::visit (AST::Enum &enum_item) -{} -void -TypeResolution::visit (AST::Union &union_item) -{} - -void -TypeResolution::visit (AST::ConstantItem &const_item) -{ - printf ("ConstantItem: %s\n", const_item.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::StaticItem &static_item) -{} -void -TypeResolution::visit (AST::TraitItemFunc &item) -{} -void -TypeResolution::visit (AST::TraitItemMethod &item) -{} -void -TypeResolution::visit (AST::TraitItemConst &item) -{} -void -TypeResolution::visit (AST::TraitItemType &item) -{} -void -TypeResolution::visit (AST::Trait &trait) -{} -void -TypeResolution::visit (AST::InherentImpl &impl) -{} -void -TypeResolution::visit (AST::TraitImpl &impl) -{} -// void TypeResolution::visit(ExternalItem& item) {} -void -TypeResolution::visit (AST::ExternalStaticItem &item) -{} -void -TypeResolution::visit (AST::ExternalFunctionItem &item) -{} -void -TypeResolution::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -TypeResolution::visit (AST::MacroMatchFragment &match) -{} -void -TypeResolution::visit (AST::MacroMatchRepetition &match) -{} -void -TypeResolution::visit (AST::MacroMatcher &matcher) -{} -void -TypeResolution::visit (AST::MacroRulesDefinition &rules_def) -{} -void -TypeResolution::visit (AST::MacroInvocation ¯o_invoc) -{} -void -TypeResolution::visit (AST::MetaItemPath &meta_item) -{} -void -TypeResolution::visit (AST::MetaItemSeq &meta_item) -{} -void -TypeResolution::visit (AST::MetaWord &meta_item) -{} -void -TypeResolution::visit (AST::MetaNameValueStr &meta_item) -{} -void -TypeResolution::visit (AST::MetaListPaths &meta_item) -{} -void -TypeResolution::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -TypeResolution::visit (AST::LiteralPattern &pattern) -{ - printf ("LiteralPattern: %s\n", pattern.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::IdentifierPattern &pattern) -{ - letPatternBuffer.push_back (pattern); -} - -void -TypeResolution::visit (AST::WildcardPattern &pattern) -{} -// void TypeResolution::visit(RangePatternBound& bound) {} -void -TypeResolution::visit (AST::RangePatternBoundLiteral &bound) -{} -void -TypeResolution::visit (AST::RangePatternBoundPath &bound) -{} -void -TypeResolution::visit (AST::RangePatternBoundQualPath &bound) -{} -void -TypeResolution::visit (AST::RangePattern &pattern) -{} -void -TypeResolution::visit (AST::ReferencePattern &pattern) -{} -// void TypeResolution::visit(StructPatternField& field) {} -void -TypeResolution::visit (AST::StructPatternFieldTuplePat &field) -{} -void -TypeResolution::visit (AST::StructPatternFieldIdentPat &field) -{} -void -TypeResolution::visit (AST::StructPatternFieldIdent &field) -{} -void -TypeResolution::visit (AST::StructPattern &pattern) -{} -// void TypeResolution::visit(TupleStructItems& tuple_items) {} -void -TypeResolution::visit (AST::TupleStructItemsNoRange &tuple_items) -{} -void -TypeResolution::visit (AST::TupleStructItemsRange &tuple_items) -{} -void -TypeResolution::visit (AST::TupleStructPattern &pattern) -{} -// void TypeResolution::visit(TuplePatternItems& tuple_items) {} -void -TypeResolution::visit (AST::TuplePatternItemsMultiple &tuple_items) -{} -void -TypeResolution::visit (AST::TuplePatternItemsRanged &tuple_items) -{} -void -TypeResolution::visit (AST::TuplePattern &pattern) -{} -void -TypeResolution::visit (AST::GroupedPattern &pattern) -{} -void -TypeResolution::visit (AST::SlicePattern &pattern) -{} - -// rust-stmt.h -void -TypeResolution::visit (AST::EmptyStmt &stmt) -{} - -void -TypeResolution::visit (AST::LetStmt &stmt) -{ - scope.InsertLocal (stmt.as_string (), &stmt); - if (!stmt.has_init_expr () && !stmt.has_type ()) - { - rust_error_at (stmt.get_locus (), - "E0282: type annotations or init expression needed"); - return; - } - - AST::Type *inferedType = nullptr; - if (stmt.has_init_expr ()) - { - auto before = typeBuffer.size (); - stmt.get_init_expr ()->accept_vis (*this); - - if (typeBuffer.size () <= before) - { - rust_error_at ( - stmt.get_init_expr ()->get_locus_slow (), - "unable to determine type for declaration from init expr"); - return; - } - - inferedType = typeBuffer.back (); - typeBuffer.pop_back (); - - if (inferedType == NULL) - { - rust_error_at (stmt.get_init_expr ()->get_locus_slow (), - "void type found for statement initialisation"); - return; - } - } - - if (stmt.has_type () && stmt.has_init_expr ()) - { - if (!typesAreCompatible (stmt.get_type ().get (), inferedType, - stmt.get_init_expr ()->get_locus_slow ())) - { - return; - } - } - else if (stmt.has_type ()) - { - auto before = typeComparisonBuffer.size (); - stmt.get_type ()->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (stmt.get_locus (), "failed to understand type for lhs"); - return; - } - auto typeString = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - // AST::Type *val = NULL; - // if (!scope.LookupType (typeString, &val)) - // { - // rust_error_at (stmt.locus, "LetStmt has unknown type: %s", - // stmt.type->as_string ().c_str ()); - // return; - // } - } - else if (inferedType != nullptr) - { - auto before = typeComparisonBuffer.size (); - inferedType->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (stmt.get_locus (), "failed to understand type for lhs"); - return; - } - auto typeString = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - // AST::Type *val = NULL; - // if (!scope.LookupType (typeString, &val)) - // { - // rust_error_at (stmt.get_locus (), "Inferred unknown type: %s", - // inferedType->as_string ().c_str ()); - // return; - // } - } - else - { - rust_fatal_error (stmt.get_locus (), "Failed to determine any type for LetStmt"); - return; - } - - // ensure the decl has the type set for compilation later on - if (!stmt.has_type ()) - { - stmt.inferedType = inferedType; - } - - // get all the names part of this declaration and add the types to the scope - stmt.get_pattern ()->accept_vis (*this); - for (auto &pattern : letPatternBuffer) - scope.InsertType (pattern.get_ident (), inferedType); - - letPatternBuffer.clear (); -} - -void -TypeResolution::visit (AST::ExprStmtWithoutBlock &stmt) -{ - stmt.get_expr ()->accept_vis (*this); -} - -void -TypeResolution::visit (AST::ExprStmtWithBlock &stmt) -{ - scope.Push (); - stmt.get_expr ()->accept_vis (*this); - auto localMap = scope.PeekLocals (); - for (auto &[_, value] : localMap) - { - stmt.locals.push_back (value); - } - scope.Pop (); -} - -// rust-type.h -void -TypeResolution::visit (AST::TraitBound &bound) -{} - -void -TypeResolution::visit (AST::ImplTraitType &type) -{} - -void -TypeResolution::visit (AST::TraitObjectType &type) -{} -void -TypeResolution::visit (AST::ParenthesisedType &type) -{} -void -TypeResolution::visit (AST::ImplTraitTypeOneBound &type) -{} -void -TypeResolution::visit (AST::TraitObjectTypeOneBound &type) -{} -void -TypeResolution::visit (AST::TupleType &type) -{} -void -TypeResolution::visit (AST::NeverType &type) -{} -void -TypeResolution::visit (AST::RawPointerType &type) -{} -void -TypeResolution::visit (AST::ReferenceType &type) -{} - -void -TypeResolution::visit (AST::ArrayType &type) -{ - typeComparisonBuffer.push_back (type.get_elem_type ()->as_string ()); -} - -void -TypeResolution::visit (AST::SliceType &type) -{} -void -TypeResolution::visit (AST::InferredType &type) -{} -void -TypeResolution::visit (AST::BareFunctionType &type) -{} - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-type-resolution.h b/gcc/rust/analysis/rust-type-resolution.h deleted file mode 100644 index 2f61a39..0000000 --- a/gcc/rust/analysis/rust-type-resolution.h +++ /dev/null @@ -1,334 +0,0 @@ -// Copyright (C) 2020 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. -#pragma once - -#include "rust-resolution.h" - -namespace Rust { -namespace Analysis { - -class TypeScoping -{ -public: - TypeScoping () {} - - ~TypeScoping () {} - - void Push () - { - functionScope.Push (); - localsPerBlock.Push (); - structsPerBlock.Push (); - typeScope.Push (); - } - - void Pop () - { - functionScope.Pop (); - localsPerBlock.Pop (); - structsPerBlock.Pop (); - typeScope.Pop (); - } - - void InsertFunction (std::string ident, AST::Function *fn) - { - functionScope.Insert (ident, fn); - } - - bool LookupFunction (std::string ident, AST::Function **fn) - { - return functionScope.Lookup (ident, fn); - } - - void PushFunction (AST::Function *fn) { functionStack.push_back (fn); } - - void PopFunction () { functionStack.pop_back (); } - - AST::Function *CurrentFunction () { return functionStack.back (); } - - void InsertLocal (std::string ident, AST::LetStmt *let) - { - localsPerBlock.Insert (ident, let); - } - - bool LookupLocal (std::string ident, AST::LetStmt **let) - { - return localsPerBlock.Lookup (ident, let); - } - - std ::map<std::string, AST::LetStmt *> PeekLocals () - { - return localsPerBlock.Peek (); - } - - void InsertStruct (std::string ident, AST::StructStruct *s) - { - structsPerBlock.Insert (ident, s); - } - - bool LookupStruct (std::string ident, AST::StructStruct **s) - { - return structsPerBlock.Lookup (ident, s); - } - - void InsertType (std::string ident, AST::Type *s) - { - typeScope.Insert (ident, s); - } - - bool LookupType (std::string ident, AST::Type **s) - { - return typeScope.Lookup (ident, s); - } - -private: - std::vector<AST::Function *> functionStack; - - Scope<AST::Function *> functionScope; - Scope<AST::LetStmt *> localsPerBlock; - Scope<AST::StructStruct *> structsPerBlock; - Scope<AST::Type *> typeScope; -}; - -class TypeResolution : public Resolution -{ - friend class TypeScoping; - -public: - ~TypeResolution (); - static bool Resolve (AST::Crate &crate, TopLevelScan &toplevel); - - // visitor impl - // rust-ast.h - // void visit(AttrInput& attr_input); - // void visit(TokenTree& token_tree); - // void visit(MacroMatch& macro_match); - void visit (AST::Token &tok) override; - void visit (AST::DelimTokenTree &delim_tok_tree) override; - void visit (AST::AttrInputMetaItemContainer &input) override; - // void visit(MetaItem& meta_item) override; - // void vsit(Stmt& stmt) override; - // void visit(Expr& expr) override; - void visit (AST::IdentifierExpr &ident_expr) override; - // void visit(Pattern& pattern) override; - // void visit(Type& type) override; - // void visit(TypeParamBound& type_param_bound) override; - void visit (AST::Lifetime &lifetime) override; - // void visit(GenericParam& generic_param) override; - void visit (AST::LifetimeParam &lifetime_param) override; - // void visit(TraitItem& trait_item) override; - // void visit(InherentImplItem& inherent_impl_item) override; - // void visit(TraitImplItem& trait_impl_item) override; - void visit (AST::MacroInvocationSemi ¯o) override; - - // rust-path.h - void visit (AST::PathInExpression &path) override; - void visit (AST::TypePathSegment &segment) override; - void visit (AST::TypePathSegmentGeneric &segment) override; - void visit (AST::TypePathSegmentFunction &segment) override; - void visit (AST::TypePath &path) override; - void visit (AST::QualifiedPathInExpression &path) override; - void visit (AST::QualifiedPathInType &path) override; - - // rust-expr.h - void visit (AST::LiteralExpr &expr) override; - void visit (AST::AttrInputLiteral &attr_input) override; - void visit (AST::MetaItemLitExpr &meta_item) override; - void visit (AST::MetaItemPathLit &meta_item) override; - void visit (AST::BorrowExpr &expr) override; - void visit (AST::DereferenceExpr &expr) override; - void visit (AST::ErrorPropagationExpr &expr) override; - void visit (AST::NegationExpr &expr) override; - void visit (AST::ArithmeticOrLogicalExpr &expr) override; - void visit (AST::ComparisonExpr &expr) override; - void visit (AST::LazyBooleanExpr &expr) override; - void visit (AST::TypeCastExpr &expr) override; - void visit (AST::AssignmentExpr &expr) override; - void visit (AST::CompoundAssignmentExpr &expr) override; - void visit (AST::GroupedExpr &expr) override; - // void visit(ArrayElems& elems) override; - void visit (AST::ArrayElemsValues &elems) override; - void visit (AST::ArrayElemsCopied &elems) override; - void visit (AST::ArrayExpr &expr) override; - void visit (AST::ArrayIndexExpr &expr) override; - void visit (AST::TupleExpr &expr) override; - void visit (AST::TupleIndexExpr &expr) override; - void visit (AST::StructExprStruct &expr) override; - // void visit(StructExprField& field) override; - void visit (AST::StructExprFieldIdentifier &field) override; - void visit (AST::StructExprFieldIdentifierValue &field) override; - void visit (AST::StructExprFieldIndexValue &field) override; - void visit (AST::StructExprStructFields &expr) override; - void visit (AST::StructExprStructBase &expr) override; - void visit (AST::StructExprTuple &expr) override; - void visit (AST::StructExprUnit &expr) override; - // void visit(EnumExprField& field) override; - void visit (AST::EnumExprFieldIdentifier &field) override; - void visit (AST::EnumExprFieldIdentifierValue &field) override; - void visit (AST::EnumExprFieldIndexValue &field) override; - void visit (AST::EnumExprStruct &expr) override; - void visit (AST::EnumExprTuple &expr) override; - void visit (AST::EnumExprFieldless &expr) override; - void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; - void visit (AST::FieldAccessExpr &expr) override; - void visit (AST::ClosureExprInner &expr) override; - void visit (AST::BlockExpr &expr) override; - void visit (AST::ClosureExprInnerTyped &expr) override; - void visit (AST::ContinueExpr &expr) override; - void visit (AST::BreakExpr &expr) override; - void visit (AST::RangeFromToExpr &expr) override; - void visit (AST::RangeFromExpr &expr) override; - void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &expr) override; - void visit (AST::RangeFromToInclExpr &expr) override; - void visit (AST::RangeToInclExpr &expr) override; - void visit (AST::ReturnExpr &expr) override; - void visit (AST::UnsafeBlockExpr &expr) override; - void visit (AST::LoopExpr &expr) override; - void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::WhileLetLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; - void visit (AST::IfExpr &expr) override; - void visit (AST::IfExprConseqElse &expr) override; - void visit (AST::IfExprConseqIf &expr) override; - void visit (AST::IfExprConseqIfLet &expr) override; - void visit (AST::IfLetExpr &expr) override; - void visit (AST::IfLetExprConseqElse &expr) override; - void visit (AST::IfLetExprConseqIf &expr) override; - void visit (AST::IfLetExprConseqIfLet &expr) override; - // void visit(MatchCase& match_case) override; - // void visit (AST::MatchCaseBlockExpr &match_case) override; - // void visit (AST::MatchCaseExpr &match_case) override; - void visit (AST::MatchExpr &expr) override; - void visit (AST::AwaitExpr &expr) override; - void visit (AST::AsyncBlockExpr &expr) override; - - // rust-item.h - void visit (AST::TypeParam ¶m) override; - // void visit(WhereClauseItem& item) override; - void visit (AST::LifetimeWhereClauseItem &item) override; - void visit (AST::TypeBoundWhereClauseItem &item) override; - void visit (AST::Method &method) override; - void visit (AST::ModuleBodied &module) override; - void visit (AST::ModuleNoBody &module) override; - void visit (AST::ExternCrate &crate) override; - // void visit(UseTree& use_tree) override; - void visit (AST::UseTreeGlob &use_tree) override; - void visit (AST::UseTreeList &use_tree) override; - void visit (AST::UseTreeRebind &use_tree) override; - void visit (AST::UseDeclaration &use_decl) override; - void visit (AST::Function &function) override; - void visit (AST::TypeAlias &type_alias) override; - void visit (AST::StructStruct &struct_item) override; - void visit (AST::TupleStruct &tuple_struct) override; - void visit (AST::EnumItem &item) override; - void visit (AST::EnumItemTuple &item) override; - void visit (AST::EnumItemStruct &item) override; - void visit (AST::EnumItemDiscriminant &item) override; - void visit (AST::Enum &enum_item) override; - void visit (AST::Union &union_item) override; - void visit (AST::ConstantItem &const_item) override; - void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemFunc &item) override; - void visit (AST::TraitItemMethod &item) override; - void visit (AST::TraitItemConst &item) override; - void visit (AST::TraitItemType &item) override; - void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl) override; - void visit (AST::TraitImpl &impl) override; - // void visit(ExternalItem& item) override; - void visit (AST::ExternalStaticItem &item) override; - void visit (AST::ExternalFunctionItem &item) override; - void visit (AST::ExternBlock &block) override; - - // rust-macro.h - void visit (AST::MacroMatchFragment &match) override; - void visit (AST::MacroMatchRepetition &match) override; - void visit (AST::MacroMatcher &matcher) override; - void visit (AST::MacroRulesDefinition &rules_def) override; - void visit (AST::MacroInvocation ¯o_invoc) override; - void visit (AST::MetaItemPath &meta_item) override; - void visit (AST::MetaItemSeq &meta_item) override; - void visit (AST::MetaWord &meta_item) override; - void visit (AST::MetaNameValueStr &meta_item) override; - void visit (AST::MetaListPaths &meta_item) override; - void visit (AST::MetaListNameValueStr &meta_item) override; - - // rust-pattern.h - void visit (AST::LiteralPattern &pattern) override; - void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::WildcardPattern &pattern) override; - // void visit(RangePatternBound& bound) override; - void visit (AST::RangePatternBoundLiteral &bound) override; - void visit (AST::RangePatternBoundPath &bound) override; - void visit (AST::RangePatternBoundQualPath &bound) override; - void visit (AST::RangePattern &pattern) override; - void visit (AST::ReferencePattern &pattern) override; - // void visit(StructPatternField& field) override; - void visit (AST::StructPatternFieldTuplePat &field) override; - void visit (AST::StructPatternFieldIdentPat &field) override; - void visit (AST::StructPatternFieldIdent &field) override; - void visit (AST::StructPattern &pattern) override; - // void visit(TupleStructItems& tuple_items) override; - void visit (AST::TupleStructItemsNoRange &tuple_items) override; - void visit (AST::TupleStructItemsRange &tuple_items) override; - void visit (AST::TupleStructPattern &pattern) override; - // void visit(TuplePatternItems& tuple_items) override; - void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - void visit (AST::TuplePatternItemsRanged &tuple_items) override; - void visit (AST::TuplePattern &pattern) override; - void visit (AST::GroupedPattern &pattern) override; - void visit (AST::SlicePattern &pattern) override; - - // rust-stmt.h - void visit (AST::EmptyStmt &stmt) override; - void visit (AST::LetStmt &stmt) override; - void visit (AST::ExprStmtWithoutBlock &stmt) override; - void visit (AST::ExprStmtWithBlock &stmt) override; - - // rust-type.h - void visit (AST::TraitBound &bound) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::TraitObjectType &type) override; - void visit (AST::ParenthesisedType &type) override; - void visit (AST::ImplTraitTypeOneBound &type) override; - void visit (AST::TraitObjectTypeOneBound &type) override; - void visit (AST::TupleType &type) override; - void visit (AST::NeverType &type) override; - void visit (AST::RawPointerType &type) override; - void visit (AST::ReferenceType &type) override; - void visit (AST::ArrayType &type) override; - void visit (AST::SliceType &type) override; - void visit (AST::InferredType &type) override; - void visit (AST::BareFunctionType &type) override; - -private: - TypeResolution (AST::Crate &crate, TopLevelScan &toplevel); - bool go () override; - bool typesAreCompatible (AST::Type *lhs, AST::Type *rhs, Location locus); - AST::Function *lookupFndecl (AST::Expr *expr); - bool isTypeInScope (AST::Type *type, Location locus); - - TypeScoping scope; - std::unique_ptr<std::string> identifierBuffer; - std::unique_ptr<int> tupleIndexBuffer; -}; - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-type-visitor.h b/gcc/rust/analysis/rust-type-visitor.h deleted file mode 100644 index 8cfe156..0000000 --- a/gcc/rust/analysis/rust-type-visitor.h +++ /dev/null @@ -1,261 +0,0 @@ -// rust-type-visitor.h -- Rust AST Visitor to AST::Type specific -// Copyright (C) 2020 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// <http://www.gnu.org/licenses/>. - -#ifndef RUST_TYPE_VISITOR_H -#define RUST_TYPE_VISITOR_H - -#include "rust-system.h" -#include "rust-ast-full.h" -#include "rust-ast-visitor.h" -#include "rust-scan.h" - -namespace Rust { -namespace Analysis { - -class BaseTypeVisitor : public AST::ASTVisitor -{ -public: - // visitor impl - // rust-ast.h - // virtual void visit(AttrInput& attr_input); - // virtual void visit(TokenTree& token_tree); - // virtual void visit(MacroMatch& macro_match); - virtual void visit (AST::Token &tok) override {} - virtual void visit (AST::DelimTokenTree &delim_tok_tree) override {} - virtual void visit (AST::AttrInputMetaItemContainer &input) override {} - // virtual void visit(MetaItem& meta_item) override {} - // void vsit(Stmt& stmt) override {} - // virtual void visit(Expr& expr) override {} - virtual void visit (AST::IdentifierExpr &ident_expr) override {} - // virtual void visit(Pattern& pattern) override {} - // virtual void visit(Type& type) override {} - // virtual void visit(TypeParamBound& type_param_bound) override {} - virtual void visit (AST::Lifetime &lifetime) override {} - // virtual void visit(GenericParam& generic_param) override {} - virtual void visit (AST::LifetimeParam &lifetime_param) override {} - // virtual void visit(TraitItem& trait_item) override {} - // virtual void visit(InherentImplItem& inherent_impl_item) override {} - // virtual void visit(TraitImplItem& trait_impl_item) override {} - virtual void visit (AST::MacroInvocationSemi ¯o) override {} - - // rust-path.h - virtual void visit (AST::PathInExpression &path) override {} - virtual void visit (AST::TypePathSegment &segment) override {} - virtual void visit (AST::TypePathSegmentGeneric &segment) override {} - virtual void visit (AST::TypePathSegmentFunction &segment) override {} - virtual void visit (AST::TypePath &path) override {} - virtual void visit (AST::QualifiedPathInExpression &path) override {} - virtual void visit (AST::QualifiedPathInType &path) override {} - - // rust-expr.h - virtual void visit (AST::LiteralExpr &expr) override {} - virtual void visit (AST::AttrInputLiteral &attr_input) override {} - virtual void visit (AST::MetaItemLitExpr &meta_item) override {} - virtual void visit (AST::MetaItemPathLit &meta_item) override {} - virtual void visit (AST::BorrowExpr &expr) override {} - virtual void visit (AST::DereferenceExpr &expr) override {} - virtual void visit (AST::ErrorPropagationExpr &expr) override {} - virtual void visit (AST::NegationExpr &expr) override {} - virtual void visit (AST::ArithmeticOrLogicalExpr &expr) override {} - virtual void visit (AST::ComparisonExpr &expr) override {} - virtual void visit (AST::LazyBooleanExpr &expr) override {} - virtual void visit (AST::TypeCastExpr &expr) override {} - virtual void visit (AST::AssignmentExpr &expr) override {} - virtual void visit (AST::CompoundAssignmentExpr &expr) override {} - virtual void visit (AST::GroupedExpr &expr) override {} - // virtual void visit(ArrayElems& elems) override {} - virtual void visit (AST::ArrayElemsValues &elems) override {} - virtual void visit (AST::ArrayElemsCopied &elems) override {} - virtual void visit (AST::ArrayExpr &expr) override {} - virtual void visit (AST::ArrayIndexExpr &expr) override {} - virtual void visit (AST::TupleExpr &expr) override {} - virtual void visit (AST::TupleIndexExpr &expr) override {} - virtual void visit (AST::StructExprStruct &expr) override {} - // virtual void visit(StructExprField& field) override {} - virtual void visit (AST::StructExprFieldIdentifier &field) override {} - virtual void visit (AST::StructExprFieldIdentifierValue &field) override {} - virtual void visit (AST::StructExprFieldIndexValue &field) override {} - virtual void visit (AST::StructExprStructFields &expr) override {} - virtual void visit (AST::StructExprStructBase &expr) override {} - virtual void visit (AST::StructExprTuple &expr) override {} - virtual void visit (AST::StructExprUnit &expr) override {} - // virtual void visit(EnumExprField& field) override {} - virtual void visit (AST::EnumExprFieldIdentifier &field) override {} - virtual void visit (AST::EnumExprFieldIdentifierValue &field) override {} - virtual void visit (AST::EnumExprFieldIndexValue &field) override {} - virtual void visit (AST::EnumExprStruct &expr) override {} - virtual void visit (AST::EnumExprTuple &expr) override {} - virtual void visit (AST::EnumExprFieldless &expr) override {} - virtual void visit (AST::CallExpr &expr) override {} - virtual void visit (AST::MethodCallExpr &expr) override {} - virtual void visit (AST::FieldAccessExpr &expr) override {} - virtual void visit (AST::ClosureExprInner &expr) override {} - virtual void visit (AST::BlockExpr &expr) override {} - virtual void visit (AST::ClosureExprInnerTyped &expr) override {} - virtual void visit (AST::ContinueExpr &expr) override {} - virtual void visit (AST::BreakExpr &expr) override {} - virtual void visit (AST::RangeFromToExpr &expr) override {} - virtual void visit (AST::RangeFromExpr &expr) override {} - virtual void visit (AST::RangeToExpr &expr) override {} - virtual void visit (AST::RangeFullExpr &expr) override {} - virtual void visit (AST::RangeFromToInclExpr &expr) override {} - virtual void visit (AST::RangeToInclExpr &expr) override {} - virtual void visit (AST::ReturnExpr &expr) override {} - virtual void visit (AST::UnsafeBlockExpr &expr) override {} - virtual void visit (AST::LoopExpr &expr) override {} - virtual void visit (AST::WhileLoopExpr &expr) override {} - virtual void visit (AST::WhileLetLoopExpr &expr) override {} - virtual void visit (AST::ForLoopExpr &expr) override {} - virtual void visit (AST::IfExpr &expr) override {} - virtual void visit (AST::IfExprConseqElse &expr) override {} - virtual void visit (AST::IfExprConseqIf &expr) override {} - virtual void visit (AST::IfExprConseqIfLet &expr) override {} - virtual void visit (AST::IfLetExpr &expr) override {} - virtual void visit (AST::IfLetExprConseqElse &expr) override {} - virtual void visit (AST::IfLetExprConseqIf &expr) override {} - virtual void visit (AST::IfLetExprConseqIfLet &expr) override {} - // virtual void visit(MatchCase& match_case) override {} - // virtual void visit (AST::MatchCaseBlockExpr &match_case) override {} - // virtual void visit (AST::MatchCaseExpr &match_case) override {} - virtual void visit (AST::MatchExpr &expr) override {} - virtual void visit (AST::AwaitExpr &expr) override {} - virtual void visit (AST::AsyncBlockExpr &expr) override {} - - // rust-item.h - virtual void visit (AST::TypeParam ¶m) override {} - // virtual void visit(WhereClauseItem& item) override {} - virtual void visit (AST::LifetimeWhereClauseItem &item) override {} - virtual void visit (AST::TypeBoundWhereClauseItem &item) override {} - virtual void visit (AST::Method &method) override {} - virtual void visit (AST::ModuleBodied &module) override {} - virtual void visit (AST::ModuleNoBody &module) override {} - virtual void visit (AST::ExternCrate &crate) override {} - // virtual void visit(UseTree& use_tree) override {} - virtual void visit (AST::UseTreeGlob &use_tree) override {} - virtual void visit (AST::UseTreeList &use_tree) override {} - virtual void visit (AST::UseTreeRebind &use_tree) override {} - virtual void visit (AST::UseDeclaration &use_decl) override {} - virtual void visit (AST::Function &function) override {} - virtual void visit (AST::TypeAlias &type_alias) override {} - virtual void visit (AST::StructStruct &struct_item) override {} - virtual void visit (AST::TupleStruct &tuple_struct) override {} - virtual void visit (AST::EnumItem &item) override {} - virtual void visit (AST::EnumItemTuple &item) override {} - virtual void visit (AST::EnumItemStruct &item) override {} - virtual void visit (AST::EnumItemDiscriminant &item) override {} - virtual void visit (AST::Enum &enum_item) override {} - virtual void visit (AST::Union &union_item) override {} - virtual void visit (AST::ConstantItem &const_item) override {} - virtual void visit (AST::StaticItem &static_item) override {} - virtual void visit (AST::TraitItemFunc &item) override {} - virtual void visit (AST::TraitItemMethod &item) override {} - virtual void visit (AST::TraitItemConst &item) override {} - virtual void visit (AST::TraitItemType &item) override {} - virtual void visit (AST::Trait &trait) override {} - virtual void visit (AST::InherentImpl &impl) override {} - virtual void visit (AST::TraitImpl &impl) override {} - // virtual void visit(ExternalItem& item) override {} - virtual void visit (AST::ExternalStaticItem &item) override {} - virtual void visit (AST::ExternalFunctionItem &item) override {} - virtual void visit (AST::ExternBlock &block) override {} - - // rust-macro.h - virtual void visit (AST::MacroMatchFragment &match) override {} - virtual void visit (AST::MacroMatchRepetition &match) override {} - virtual void visit (AST::MacroMatcher &matcher) override {} - virtual void visit (AST::MacroRulesDefinition &rules_def) override {} - virtual void visit (AST::MacroInvocation ¯o_invoc) override {} - virtual void visit (AST::MetaItemPath &meta_item) override {} - virtual void visit (AST::MetaItemSeq &meta_item) override {} - virtual void visit (AST::MetaWord &meta_item) override {} - virtual void visit (AST::MetaNameValueStr &meta_item) override {} - virtual void visit (AST::MetaListPaths &meta_item) override {} - virtual void visit (AST::MetaListNameValueStr &meta_item) override {} - - // rust-pattern.h - virtual void visit (AST::LiteralPattern &pattern) override {} - virtual void visit (AST::IdentifierPattern &pattern) override {} - virtual void visit (AST::WildcardPattern &pattern) override {} - // virtual void visit(RangePatternBound& bound) override {} - virtual void visit (AST::RangePatternBoundLiteral &bound) override {} - virtual void visit (AST::RangePatternBoundPath &bound) override {} - virtual void visit (AST::RangePatternBoundQualPath &bound) override {} - virtual void visit (AST::RangePattern &pattern) override {} - virtual void visit (AST::ReferencePattern &pattern) override {} - // virtual void visit(StructPatternField& field) override {} - virtual void visit (AST::StructPatternFieldTuplePat &field) override {} - virtual void visit (AST::StructPatternFieldIdentPat &field) override {} - virtual void visit (AST::StructPatternFieldIdent &field) override {} - virtual void visit (AST::StructPattern &pattern) override {} - // virtual void visit(TupleStructItems& tuple_items) override {} - virtual void visit (AST::TupleStructItemsNoRange &tuple_items) override {} - virtual void visit (AST::TupleStructItemsRange &tuple_items) override {} - virtual void visit (AST::TupleStructPattern &pattern) override {} - // virtual void visit(TuplePatternItems& tuple_items) override {} - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) override {} - virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override {} - virtual void visit (AST::TuplePattern &pattern) override {} - virtual void visit (AST::GroupedPattern &pattern) override {} - virtual void visit (AST::SlicePattern &pattern) override {} - - // rust-stmt.h - virtual void visit (AST::EmptyStmt &stmt) override {} - virtual void visit (AST::LetStmt &stmt) override {} - virtual void visit (AST::ExprStmtWithoutBlock &stmt) override {} - virtual void visit (AST::ExprStmtWithBlock &stmt) override {} - - // rust-type.h - virtual void visit (AST::TraitBound &bound) override {} - virtual void visit (AST::ImplTraitType &type) override {} - virtual void visit (AST::TraitObjectType &type) override {} - virtual void visit (AST::ParenthesisedType &type) override {} - virtual void visit (AST::ImplTraitTypeOneBound &type) override {} - virtual void visit (AST::TraitObjectTypeOneBound &type) override {} - virtual void visit (AST::TupleType &type) override {} - virtual void visit (AST::NeverType &type) override {} - virtual void visit (AST::RawPointerType &type) override {} - virtual void visit (AST::ReferenceType &type) override {} - virtual void visit (AST::ArrayType &type) override {} - virtual void visit (AST::SliceType &type) override {} - virtual void visit (AST::InferredType &type) override {} - virtual void visit (AST::BareFunctionType &type) override {} -}; - -class ArrayTypeVisitor : public BaseTypeVisitor -{ -public: - static AST::ArrayType *Resolve (AST::Type *type) - { - ArrayTypeVisitor vis; - type->accept_vis (vis); - return vis.resolved; - } - - virtual void visit (AST::ArrayType &type) override { resolved = &type; }; - -private: - ArrayTypeVisitor () : resolved (nullptr) {} - - AST::ArrayType *resolved; -}; - -} // namespace Analysis -} // namespace Rust - -#endif // RUST_TYPE_VISITOR_H diff --git a/gcc/rust/analysis/scope.h b/gcc/rust/analysis/scope.h deleted file mode 100644 index 41bcee6..0000000 --- a/gcc/rust/analysis/scope.h +++ /dev/null @@ -1,57 +0,0 @@ -#pragma once - -#include "rust-system.h" -#include "rust-ast-full.h" - -namespace Rust { -namespace Analysis { - -template <class T> class Scope -{ -public: - Scope () : scopeStack () {} - - ~Scope () {} - - bool Insert (std::string key, T val) - { - if (scopeStack.back ().find (key) != scopeStack.back ().end ()) - { - return false; - } - - scopeStack.back ().insert (std::make_pair (key, std::move (val))); - return true; - } - - bool Lookup (std::string key, T *result) - { - for (auto it = scopeStack.rbegin (); it != scopeStack.rend (); ++it) - { - auto lookup = it->find (key); - if (lookup != it->end ()) - { - *result = lookup->second; - return true; - } - } - return false; - } - - void Push () { scopeStack.push_back ({}); } - - std ::map<std::string, T> Pop () - { - auto toplevel = scopeStack.back (); - scopeStack.pop_back (); - return toplevel; - } - - std ::map<std::string, T> Peek () { return scopeStack.back (); } - -private: - std::vector<std::map<std::string, T> > scopeStack; -}; - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/ast/rust-ast-full-decls.h b/gcc/rust/ast/rust-ast-full-decls.h index 9b604a5..ebd2b2a 100644 --- a/gcc/rust/ast/rust-ast-full-decls.h +++ b/gcc/rust/ast/rust-ast-full-decls.h @@ -1,266 +1,286 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + #ifndef RUST_AST_FULL_DECLS_H #define RUST_AST_FULL_DECLS_H -// Forward declarations for all AST classes. Useful for not having to include all definitions. + +// Forward declarations for all AST classes. Useful for not having to include +// all definitions. namespace Rust { - namespace AST { - // rust-ast.h - class AttrInput; - class TokenTree; - class MacroMatch; - class Token; - struct Literal; - class DelimTokenTree; - class PathSegment; - class SimplePathSegment; - class SimplePath; - struct Attribute; - class MetaItemInner; - class AttrInputMetaItemContainer; - class MetaItem; - class Stmt; - class Item; - class Expr; - class ExprWithoutBlock; - class IdentifierExpr; - class Pattern; - class Type; - class TypeNoBounds; - class TypeParamBound; - class Lifetime; - class GenericParam; - class LifetimeParam; - class MacroItem; - class TraitItem; - class InherentImplItem; - class TraitImplItem; - class MacroInvocationSemi; - struct Crate; - class PathExpr; +namespace AST { +// rust-ast.h +class AttrInput; +class TokenTree; +class MacroMatch; +class Token; +struct Literal; +class DelimTokenTree; +class PathSegment; +class SimplePathSegment; +class SimplePath; +struct Attribute; +class MetaItemInner; +class AttrInputMetaItemContainer; +class MetaItem; +class Stmt; +class Item; +class Expr; +class ExprWithoutBlock; +class IdentifierExpr; +class Pattern; +class Type; +class TypeNoBounds; +class TypeParamBound; +class Lifetime; +class GenericParam; +class LifetimeParam; +class MacroItem; +class TraitItem; +class InherentImplItem; +class TraitImplItem; +class MacroInvocationSemi; +struct Crate; +class PathExpr; - // rust-path.h - class PathIdentSegment; - struct GenericArgsBinding; - struct GenericArgs; - class PathExprSegment; - class PathPattern; - class PathInExpression; - class TypePathSegment; - class TypePathSegmentGeneric; - struct TypePathFunction; - class TypePathSegmentFunction; - class TypePath; - struct QualifiedPathType; - class QualifiedPathInExpression; - class QualifiedPathInType; +// rust-path.h +class PathIdentSegment; +struct GenericArgsBinding; +struct GenericArgs; +class PathExprSegment; +class PathPattern; +class PathInExpression; +class TypePathSegment; +class TypePathSegmentGeneric; +struct TypePathFunction; +class TypePathSegmentFunction; +class TypePath; +struct QualifiedPathType; +class QualifiedPathInExpression; +class QualifiedPathInType; - // rust-expr.h - class ExprWithBlock; - class LiteralExpr; - class AttrInputLiteral; - class MetaItemLitExpr; - class MetaItemPathLit; - class OperatorExpr; - class BorrowExpr; - class DereferenceExpr; - class ErrorPropagationExpr; - class NegationExpr; - class ArithmeticOrLogicalExpr; - class ComparisonExpr; - class LazyBooleanExpr; - class TypeCastExpr; - class AssignmentExpr; - class CompoundAssignmentExpr; - class GroupedExpr; - class ArrayElems; - class ArrayElemsValues; - class ArrayElemsCopied; - class ArrayExpr; - class ArrayIndexExpr; - class TupleExpr; - class TupleIndexExpr; - class StructExpr; - class StructExprStruct; - struct StructBase; - class StructExprField; - class StructExprFieldIdentifier; - class StructExprFieldWithVal; - class StructExprFieldIdentifierValue; - class StructExprFieldIndexValue; - class StructExprStructFields; - class StructExprStructBase; - class StructExprTuple; - class StructExprUnit; - class EnumVariantExpr; - class EnumExprField; - class EnumExprFieldIdentifier; - class EnumExprFieldWithVal; - class EnumExprFieldIdentifierValue; - class EnumExprFieldIndexValue; - class EnumExprStruct; - class EnumExprTuple; - class EnumExprFieldless; - class CallExpr; - class MethodCallExpr; - class FieldAccessExpr; - struct ClosureParam; - class ClosureExpr; - class ClosureExprInner; - class BlockExpr; - class ClosureExprInnerTyped; - class ContinueExpr; - class BreakExpr; - class RangeExpr; - class RangeFromToExpr; - class RangeFromExpr; - class RangeToExpr; - class RangeFullExpr; - class RangeFromToInclExpr; - class RangeToInclExpr; - class ReturnExpr; - class UnsafeBlockExpr; - class LoopLabel; - class BaseLoopExpr; - class LoopExpr; - class WhileLoopExpr; - class WhileLetLoopExpr; - class ForLoopExpr; - class IfExpr; - class IfExprConseqElse; - class IfExprConseqIf; - class IfLetExpr; - class IfExprConseqIfLet; - class IfLetExprConseqElse; - class IfLetExprConseqIf; - class IfLetExprConseqIfLet; - struct MatchArm; - // class MatchCase; - // class MatchCaseBlockExpr; - // class MatchCaseExpr; - struct MatchCase; - class MatchExpr; - class AwaitExpr; - class AsyncBlockExpr; +// rust-expr.h +class ExprWithBlock; +class LiteralExpr; +class AttrInputLiteral; +class MetaItemLitExpr; +class MetaItemPathLit; +class OperatorExpr; +class BorrowExpr; +class DereferenceExpr; +class ErrorPropagationExpr; +class NegationExpr; +class ArithmeticOrLogicalExpr; +class ComparisonExpr; +class LazyBooleanExpr; +class TypeCastExpr; +class AssignmentExpr; +class CompoundAssignmentExpr; +class GroupedExpr; +class ArrayElems; +class ArrayElemsValues; +class ArrayElemsCopied; +class ArrayExpr; +class ArrayIndexExpr; +class TupleExpr; +class TupleIndexExpr; +class StructExpr; +class StructExprStruct; +struct StructBase; +class StructExprField; +class StructExprFieldIdentifier; +class StructExprFieldWithVal; +class StructExprFieldIdentifierValue; +class StructExprFieldIndexValue; +class StructExprStructFields; +class StructExprStructBase; +class StructExprTuple; +class StructExprUnit; +class EnumVariantExpr; +class EnumExprField; +class EnumExprFieldIdentifier; +class EnumExprFieldWithVal; +class EnumExprFieldIdentifierValue; +class EnumExprFieldIndexValue; +class EnumExprStruct; +class EnumExprTuple; +class EnumExprFieldless; +class CallExpr; +class MethodCallExpr; +class FieldAccessExpr; +struct ClosureParam; +class ClosureExpr; +class ClosureExprInner; +class BlockExpr; +class ClosureExprInnerTyped; +class ContinueExpr; +class BreakExpr; +class RangeExpr; +class RangeFromToExpr; +class RangeFromExpr; +class RangeToExpr; +class RangeFullExpr; +class RangeFromToInclExpr; +class RangeToInclExpr; +class ReturnExpr; +class UnsafeBlockExpr; +class LoopLabel; +class BaseLoopExpr; +class LoopExpr; +class WhileLoopExpr; +class WhileLetLoopExpr; +class ForLoopExpr; +class IfExpr; +class IfExprConseqElse; +class IfExprConseqIf; +class IfLetExpr; +class IfExprConseqIfLet; +class IfLetExprConseqElse; +class IfLetExprConseqIf; +class IfLetExprConseqIfLet; +struct MatchArm; +// class MatchCase; +// class MatchCaseBlockExpr; +// class MatchCaseExpr; +struct MatchCase; +class MatchExpr; +class AwaitExpr; +class AsyncBlockExpr; - // rust-stmt.h - class EmptyStmt; - class LetStmt; - class ExprStmt; - class ExprStmtWithoutBlock; - class ExprStmtWithBlock; +// rust-stmt.h +class EmptyStmt; +class LetStmt; +class ExprStmt; +class ExprStmtWithoutBlock; +class ExprStmtWithBlock; - // rust-item.h - class TypeParam; - class WhereClauseItem; - class LifetimeWhereClauseItem; - class TypeBoundWhereClauseItem; - struct WhereClause; - struct SelfParam; - struct FunctionQualifiers; - struct FunctionParam; - struct Visibility; - class Method; - class VisItem; - class Module; - class ModuleBodied; - class ModuleNoBody; - class ExternCrate; - class UseTree; - class UseTreeGlob; - class UseTreeList; - class UseTreeRebind; - class UseDeclaration; - class Function; - class TypeAlias; - class Struct; - struct StructField; - class StructStruct; - struct TupleField; - class TupleStruct; - class EnumItem; - class EnumItemTuple; - class EnumItemStruct; - class EnumItemDiscriminant; - class Enum; - class Union; - class ConstantItem; - class StaticItem; - struct TraitFunctionDecl; - class TraitItemFunc; - struct TraitMethodDecl; - class TraitItemMethod; - class TraitItemConst; - class TraitItemType; - class Trait; - class Impl; - class InherentImpl; - class TraitImpl; - class ExternalItem; - class ExternalStaticItem; - struct NamedFunctionParam; - class ExternalFunctionItem; - class ExternBlock; +// rust-item.h +class TypeParam; +class WhereClauseItem; +class LifetimeWhereClauseItem; +class TypeBoundWhereClauseItem; +struct WhereClause; +struct SelfParam; +struct FunctionQualifiers; +struct FunctionParam; +struct Visibility; +class Method; +class VisItem; +class Module; +class ModuleBodied; +class ModuleNoBody; +class ExternCrate; +class UseTree; +class UseTreeGlob; +class UseTreeList; +class UseTreeRebind; +class UseDeclaration; +class Function; +class TypeAlias; +class Struct; +struct StructField; +class StructStruct; +struct TupleField; +class TupleStruct; +class EnumItem; +class EnumItemTuple; +class EnumItemStruct; +class EnumItemDiscriminant; +class Enum; +class Union; +class ConstantItem; +class StaticItem; +struct TraitFunctionDecl; +class TraitItemFunc; +struct TraitMethodDecl; +class TraitItemMethod; +class TraitItemConst; +class TraitItemType; +class Trait; +class Impl; +class InherentImpl; +class TraitImpl; +class ExternalItem; +class ExternalStaticItem; +struct NamedFunctionParam; +class ExternalFunctionItem; +class ExternBlock; - // rust-macro.h - class MacroMatchFragment; - class MacroMatchRepetition; - class MacroMatcher; - struct MacroTranscriber; - struct MacroRule; - class MacroRulesDefinition; - class MacroInvocation; - class MetaItemPath; - class MetaItemSeq; - class MetaWord; - class MetaNameValueStr; - class MetaListPaths; - class MetaListNameValueStr; +// rust-macro.h +class MacroMatchFragment; +class MacroMatchRepetition; +class MacroMatcher; +struct MacroTranscriber; +struct MacroRule; +class MacroRulesDefinition; +class MacroInvocation; +class MetaItemPath; +class MetaItemSeq; +class MetaWord; +class MetaNameValueStr; +class MetaListPaths; +class MetaListNameValueStr; - // rust-pattern.h - class LiteralPattern; - class IdentifierPattern; - class WildcardPattern; - class RangePatternBound; - class RangePatternBoundLiteral; - class RangePatternBoundPath; - class RangePatternBoundQualPath; - class RangePattern; - class ReferencePattern; - struct StructPatternEtc; - class StructPatternField; - class StructPatternFieldTuplePat; - class StructPatternFieldIdentPat; - class StructPatternFieldIdent; - struct StructPatternElements; - class StructPattern; - class TupleStructItems; - class TupleStructItemsNoRange; - class TupleStructItemsRange; - class TupleStructPattern; - class TuplePatternItems; - class TuplePatternItemsMultiple; - class TuplePatternItemsRanged; - class TuplePattern; - class GroupedPattern; - class SlicePattern; +// rust-pattern.h +class LiteralPattern; +class IdentifierPattern; +class WildcardPattern; +class RangePatternBound; +class RangePatternBoundLiteral; +class RangePatternBoundPath; +class RangePatternBoundQualPath; +class RangePattern; +class ReferencePattern; +struct StructPatternEtc; +class StructPatternField; +class StructPatternFieldTuplePat; +class StructPatternFieldIdentPat; +class StructPatternFieldIdent; +struct StructPatternElements; +class StructPattern; +class TupleStructItems; +class TupleStructItemsNoRange; +class TupleStructItemsRange; +class TupleStructPattern; +class TuplePatternItems; +class TuplePatternItemsMultiple; +class TuplePatternItemsRanged; +class TuplePattern; +class GroupedPattern; +class SlicePattern; - // rust-type.h - class TraitBound; - class ImplTraitType; - class TraitObjectType; - class ParenthesisedType; - class ImplTraitTypeOneBound; - class TraitObjectTypeOneBound; - class TupleType; - class NeverType; - class RawPointerType; - class ReferenceType; - class ArrayType; - class SliceType; - class InferredType; - struct MaybeNamedParam; - class BareFunctionType; - } -} +// rust-type.h +class TraitBound; +class ImplTraitType; +class TraitObjectType; +class ParenthesisedType; +class ImplTraitTypeOneBound; +class TraitObjectTypeOneBound; +class TupleType; +class NeverType; +class RawPointerType; +class ReferenceType; +class ArrayType; +class SliceType; +class InferredType; +struct MaybeNamedParam; +class BareFunctionType; +} // namespace AST +} // namespace Rust -#endif
\ No newline at end of file +#endif diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index 4916e36..58bc372 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -1,18 +1,31 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + #ifndef RUST_AST_BASE_H #define RUST_AST_BASE_H // Base for AST used in gccrs, basically required by all specific ast things #include "rust-system.h" - -// STL imports -#include <memory> -#include <string> -#include <vector> +#include "rust-hir-map.h" // gccrs imports // required for AST::Token #include "rust-token.h" - #include "rust-location.h" namespace Rust { @@ -253,6 +266,10 @@ public: bool is_error () const { return value_as_string == ""; } }; +/* 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 @@ -473,7 +490,7 @@ public: std::string as_string () const; // TODO: does this require visitor pattern as not polymorphic? - + const SimplePath &get_path () const { return path; } SimplePath &get_path () { return path; } @@ -768,10 +785,15 @@ public: virtual void mark_for_strip () = 0; virtual bool is_marked_for_strip () const = 0; + NodeId get_node_id () const { return node_id; } protected: + Stmt () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + // Clone function implementation as pure virtual method virtual Stmt *clone_stmt_impl () const = 0; + + NodeId node_id; }; // Rust "item" AST node (declaration of top-level/module-level allowed stuff) @@ -848,10 +870,13 @@ public: virtual void mark_for_strip () = 0; virtual bool is_marked_for_strip () const = 0; + virtual NodeId get_node_id () const { return node_id; } + protected: // Constructor Expr (std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) - : outer_attrs (std::move (outer_attribs)) + : outer_attrs (std::move (outer_attribs)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Clone function implementation as pure virtual method @@ -863,6 +888,8 @@ protected: { outer_attrs = std::move (outer_attrs_to_set); } + + NodeId node_id; }; // AST node for an expression without an accompanying block - abstract @@ -978,9 +1005,15 @@ public: * methods. */ virtual Location get_locus_slow () const = 0; + virtual NodeId get_node_id () const { return node_id; } + protected: // Clone pattern implementation as pure virtual method virtual Pattern *clone_pattern_impl () const = 0; + + Pattern () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + + NodeId node_id; }; // forward decl for Type @@ -1015,9 +1048,15 @@ public: virtual Location get_locus_slow () const = 0; + NodeId get_node_id () const { return node_id; } + protected: + Type () : node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} + // Clone function implementation as pure virtual method virtual Type *clone_type_impl () const = 0; + + NodeId node_id; }; // A type without parentheses? - abstract @@ -1041,6 +1080,8 @@ protected: { return clone_type_no_bounds_impl (); } + + TypeNoBounds () : Type () {} }; /* Abstract base class representing a type param bound - Lifetime and TraitBound @@ -1494,19 +1535,22 @@ struct Crate * top-level one)? */ std::vector<std::unique_ptr<Item> > items; + NodeId node_id; + 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)) + inner_attrs (std::move (inner_attrs)), items (std::move (items)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Copy constructor with vector clone Crate (Crate const &other) : has_utf8bom (other.has_utf8bom), has_shebang (other.has_shebang), - inner_attrs (other.inner_attrs) + inner_attrs (other.inner_attrs), node_id (other.node_id) { items.reserve (other.items.size ()); for (const auto &e : other.items) @@ -1521,6 +1565,7 @@ public: inner_attrs = other.inner_attrs; has_shebang = other.has_shebang; has_utf8bom = other.has_utf8bom; + node_id = other.node_id; items.reserve (other.items.size ()); for (const auto &e : other.items) @@ -1546,6 +1591,8 @@ public: items.shrink_to_fit (); // TODO: is this the best way to do this? } + + NodeId get_node_id () const { return node_id; } }; // Base path expression AST node - abstract diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index f86aa54..de011c1 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -1647,7 +1647,8 @@ class StructExprFieldIdentifierValue : public StructExprFieldWithVal public: StructExprFieldIdentifierValue (Identifier field_identifier, - std::unique_ptr<Expr> field_value, Location locus) + std::unique_ptr<Expr> field_value, + Location locus) : StructExprFieldWithVal (std::move (field_value)), field_name (std::move (field_identifier)), locus (locus) {} @@ -1679,7 +1680,8 @@ class StructExprFieldIndexValue : public StructExprFieldWithVal public: StructExprFieldIndexValue (TupleIndex tuple_index, std::unique_ptr<Expr> field_value, Location locus) - : StructExprFieldWithVal (std::move (field_value)), index (tuple_index), locus (locus) + : StructExprFieldWithVal (std::move (field_value)), index (tuple_index), + locus (locus) {} std::string as_string () const override; @@ -2039,7 +2041,8 @@ class EnumExprFieldIdentifierValue : public EnumExprFieldWithVal public: EnumExprFieldIdentifierValue (Identifier field_name, - std::unique_ptr<Expr> field_value, Location locus) + std::unique_ptr<Expr> field_value, + Location locus) : EnumExprFieldWithVal (std::move (field_value)), field_name (std::move (field_name)), locus (locus) {} @@ -2071,7 +2074,8 @@ class EnumExprFieldIndexValue : public EnumExprFieldWithVal public: EnumExprFieldIndexValue (TupleIndex field_index, std::unique_ptr<Expr> field_value, Location locus) - : EnumExprFieldWithVal (std::move (field_value)), index (field_index), locus (locus) + : EnumExprFieldWithVal (std::move (field_value)), index (field_index), + locus (locus) {} std::string as_string () const override; @@ -2325,6 +2329,15 @@ public: void mark_for_strip () override { function = nullptr; } bool is_marked_for_strip () const override { return function == nullptr; } + void iterate_params (std::function<bool (Expr *)> cb) + { + for (auto it = params.begin (); it != params.end (); it++) + { + if (!cb (it->get ())) + return; + } + } + // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector<std::unique_ptr<Expr> > &get_params () const { @@ -2793,13 +2806,16 @@ public: void accept_vis (ASTVisitor &vis) override; // Can be completely empty, so have to have a separate flag. - void mark_for_strip () override - { - marked_for_strip = true; - } - bool is_marked_for_strip () const override + void mark_for_strip () override { marked_for_strip = true; } + bool is_marked_for_strip () const override { return marked_for_strip; } + + void iterate_stmts (std::function<bool (Stmt *)> cb) { - return marked_for_strip; + for (auto it = statements.begin (); it != statements.end (); it++) + { + if (!cb (it->get ())) + return; + } } // TODO: this mutable getter seems really dodgy. Think up better way. diff --git a/gcc/rust/ast/rust-item.h b/gcc/rust/ast/rust-item.h index f18124d..4b3a2d5 100644 --- a/gcc/rust/ast/rust-item.h +++ b/gcc/rust/ast/rust-item.h @@ -1,23 +1,23 @@ -#ifndef RUST_AST_ITEM_H -#define RUST_AST_ITEM_H -/* -Copyright (C) 2009-2020 Free Software Foundation, Inc. +// Copyright (C) 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/>. + +#ifndef RUST_AST_ITEM_H +#define RUST_AST_ITEM_H #include "rust-ast.h" #include "rust-path.h" @@ -504,11 +504,13 @@ public: std::unique_ptr<Type> param_type, std::vector<Attribute> outer_attrs, Location locus) : outer_attrs (std::move (outer_attrs)), locus (locus), - param_name (std::move (param_name)), type (std::move (param_type)) + param_name (std::move (param_name)), type (std::move (param_type)), + node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Copy constructor uses clone - FunctionParam (FunctionParam const &other) : locus (other.locus) + FunctionParam (FunctionParam const &other) + : locus (other.locus), node_id (other.node_id) { // guard to prevent nullptr dereference if (other.param_name != nullptr) @@ -521,6 +523,7 @@ public: FunctionParam &operator= (FunctionParam const &other) { locus = other.locus; + node_id = other.node_id; // guard to prevent nullptr dereference if (other.param_name != nullptr) @@ -569,6 +572,10 @@ public: rust_assert (type != nullptr); return type; } + NodeId get_node_id () const { return node_id; } + +protected: + NodeId node_id; }; // Visibility of item - if the item has it, then it is some form of public @@ -3320,6 +3327,7 @@ public: std::vector<std::unique_ptr<TraitItem> > trait_items, Visibility vis, std::vector<Attribute> outer_attrs, std::vector<Attribute> inner_attrs, Location locus) + : VisItem (std::move (vis), std::move (outer_attrs)), has_unsafe (is_unsafe), name (std::move (name)), generic_params (std::move (generic_params)), diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 392fc18..bd3b0f0 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -240,6 +240,8 @@ public: rust_assert (has_generic_args ()); return generic_args; } + + PathIdentSegment &get_ident_segment () { return segment_name; } }; // AST node representing a pattern that involves a "path" - abstract base class @@ -276,6 +278,15 @@ public: // TODO: this seems kinda dodgy std::vector<PathExprSegment> &get_segments () { return segments; } const std::vector<PathExprSegment> &get_segments () const { return segments; } + + void iterate_path_segments (std::function<bool (PathExprSegment &)> cb) + { + for (auto it = segments.begin (); it != segments.end (); it++) + { + if (!cb (*it)) + return; + } + } }; /* AST node representing a path-in-expression pattern (path that allows generic @@ -285,6 +296,8 @@ class PathInExpression : public PathPattern, public PathExpr bool has_opening_scope_resolution; Location locus; + NodeId _node_id; + public: std::string as_string () const override; @@ -296,7 +309,8 @@ public: = std::vector<Attribute> ()) : PathPattern (std::move (path_segments)), PathExpr (std::move (outer_attrs)), - has_opening_scope_resolution (has_opening_scope_resolution), locus (locus) + has_opening_scope_resolution (has_opening_scope_resolution), + locus (locus), _node_id (Analysis::Mappings::get ()->get_next_node_id ()) {} // Creates an error state path in expression. @@ -328,6 +342,9 @@ public: // Invalid if path is empty (error state), so base stripping on that. void mark_for_strip () override { remove_all_segments (); } bool is_marked_for_strip () const override { return is_error (); } + bool opening_scope_resolution () { return has_opening_scope_resolution; } + + NodeId get_node_id () const override { return _node_id; } protected: /* Use covariance to implement clone function as returning this object rather @@ -404,6 +421,13 @@ public: // not pure virtual as class not abstract virtual void accept_vis (ASTVisitor &vis); + + bool get_separating_scope_resolution () const + { + return has_separating_scope_resolution; + } + + PathIdentSegment get_ident_segment () { return ident_segment; }; }; // Segment used in type path with generic args @@ -635,7 +659,8 @@ public: // 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), + : TypeNoBounds (), + has_opening_scope_resolution (has_opening_scope_resolution), segments (std::move (segments)), locus (locus) {} @@ -689,6 +714,17 @@ public: { return segments; } + + size_t get_num_segments () const { return segments.size (); } + + void iterate_segments (std::function<bool (TypePathSegment *)> cb) + { + for (auto it = segments.begin (); it != segments.end (); it++) + { + if (!cb ((*it).get ())) + return; + } + } }; struct QualifiedPathType diff --git a/gcc/rust/ast/rust-pattern.h b/gcc/rust/ast/rust-pattern.h index 3a87a83..dc4d48c 100644 --- a/gcc/rust/ast/rust-pattern.h +++ b/gcc/rust/ast/rust-pattern.h @@ -69,8 +69,8 @@ public: IdentifierPattern (Identifier ident, Location locus, bool is_ref = false, bool is_mut = false, std::unique_ptr<Pattern> to_bind = nullptr) - : variable_ident (std::move (ident)), is_ref (is_ref), is_mut (is_mut), - to_bind (std::move (to_bind)), locus (locus) + : Pattern (), 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 @@ -78,7 +78,9 @@ public: : variable_ident (other.variable_ident), is_ref (other.is_ref), is_mut (other.is_mut), locus (other.locus) { - // fix to prevent null pointer dereference + node_id = other.node_id; + // fix to get prevent null pointer dereference + if (other.to_bind != nullptr) to_bind = other.to_bind->clone_pattern (); } @@ -90,6 +92,7 @@ public: is_ref = other.is_ref; is_mut = other.is_mut; locus = other.locus; + node_id = other.node_id; // fix to prevent null pointer dereference if (other.to_bind != nullptr) @@ -118,6 +121,9 @@ public: Identifier get_ident () const { return variable_ident; } + bool get_is_mut () const { return is_mut; } + bool get_is_ref () const { return is_ref; } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/backend/rust-compile-base.h b/gcc/rust/backend/rust-compile-base.h new file mode 100644 index 0000000..6410fd4 --- /dev/null +++ b/gcc/rust/backend/rust-compile-base.h @@ -0,0 +1,249 @@ + + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_BASE +#define RUST_COMPILE_BASE + +#include "rust-compile-context.h" +#include "rust-hir-visitor.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace Compile { + +class HIRCompileBase : public HIR::HIRVisitor +{ +public: + virtual ~HIRCompileBase () {} + + // rust-ast.h + // virtual void visit(AttrInput& attr_input) {} + // virtual void visit(TokenTree& token_tree) {} + // virtual void visit(MacroMatch& macro_match) {} + virtual void visit (HIR::Token &tok) {} + virtual void visit (HIR::DelimTokenTree &delim_tok_tree) {} + virtual void visit (HIR::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // virtual void visit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (HIR::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (HIR::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (HIR::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (HIR::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (HIR::PathInExpression &path) {} + virtual void visit (HIR::TypePathSegment &segment) {} + virtual void visit (HIR::TypePathSegmentGeneric &segment) {} + virtual void visit (HIR::TypePathSegmentFunction &segment) {} + virtual void visit (HIR::TypePath &path) {} + virtual void visit (HIR::QualifiedPathInExpression &path) {} + virtual void visit (HIR::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (HIR::LiteralExpr &expr) {} + virtual void visit (HIR::AttrInputLiteral &attr_input) {} + virtual void visit (HIR::MetaItemLitExpr &meta_item) {} + virtual void visit (HIR::MetaItemPathLit &meta_item) {} + virtual void visit (HIR::BorrowExpr &expr) {} + virtual void visit (HIR::DereferenceExpr &expr) {} + virtual void visit (HIR::ErrorPropagationExpr &expr) {} + virtual void visit (HIR::NegationExpr &expr) {} + virtual void visit (HIR::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (HIR::ComparisonExpr &expr) {} + virtual void visit (HIR::LazyBooleanExpr &expr) {} + virtual void visit (HIR::TypeCastExpr &expr) {} + virtual void visit (HIR::AssignmentExpr &expr) {} + virtual void visit (HIR::CompoundAssignmentExpr &expr) {} + virtual void visit (HIR::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (HIR::ArrayElemsValues &elems) {} + virtual void visit (HIR::ArrayElemsCopied &elems) {} + virtual void visit (HIR::ArrayExpr &expr) {} + virtual void visit (HIR::ArrayIndexExpr &expr) {} + virtual void visit (HIR::TupleExpr &expr) {} + virtual void visit (HIR::TupleIndexExpr &expr) {} + virtual void visit (HIR::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (HIR::StructExprFieldIdentifier &field) {} + virtual void visit (HIR::StructExprFieldIdentifierValue &field) {} + virtual void visit (HIR::StructExprFieldIndexValue &field) {} + virtual void visit (HIR::StructExprStructFields &expr) {} + virtual void visit (HIR::StructExprStructBase &expr) {} + virtual void visit (HIR::StructExprTuple &expr) {} + virtual void visit (HIR::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (HIR::EnumExprFieldIdentifier &field) {} + virtual void visit (HIR::EnumExprFieldIdentifierValue &field) {} + virtual void visit (HIR::EnumExprFieldIndexValue &field) {} + virtual void visit (HIR::EnumExprStruct &expr) {} + virtual void visit (HIR::EnumExprTuple &expr) {} + virtual void visit (HIR::EnumExprFieldless &expr) {} + virtual void visit (HIR::CallExpr &expr) {} + virtual void visit (HIR::MethodCallExpr &expr) {} + virtual void visit (HIR::FieldAccessExpr &expr) {} + virtual void visit (HIR::ClosureExprInner &expr) {} + virtual void visit (HIR::BlockExpr &expr) {} + virtual void visit (HIR::ClosureExprInnerTyped &expr) {} + virtual void visit (HIR::ContinueExpr &expr) {} + virtual void visit (HIR::BreakExpr &expr) {} + virtual void visit (HIR::RangeFromToExpr &expr) {} + virtual void visit (HIR::RangeFromExpr &expr) {} + virtual void visit (HIR::RangeToExpr &expr) {} + virtual void visit (HIR::RangeFullExpr &expr) {} + virtual void visit (HIR::RangeFromToInclExpr &expr) {} + virtual void visit (HIR::RangeToInclExpr &expr) {} + virtual void visit (HIR::ReturnExpr &expr) {} + virtual void visit (HIR::UnsafeBlockExpr &expr) {} + virtual void visit (HIR::LoopExpr &expr) {} + virtual void visit (HIR::WhileLoopExpr &expr) {} + virtual void visit (HIR::WhileLetLoopExpr &expr) {} + virtual void visit (HIR::ForLoopExpr &expr) {} + virtual void visit (HIR::IfExpr &expr) {} + virtual void visit (HIR::IfExprConseqElse &expr) {} + virtual void visit (HIR::IfExprConseqIf &expr) {} + virtual void visit (HIR::IfExprConseqIfLet &expr) {} + virtual void visit (HIR::IfLetExpr &expr) {} + virtual void visit (HIR::IfLetExprConseqElse &expr) {} + virtual void visit (HIR::IfLetExprConseqIf &expr) {} + virtual void visit (HIR::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (HIR::MatchCaseBlockExpr &match_case) {} + // virtual void visit (HIR::MatchCaseExpr &match_case) {} + virtual void visit (HIR::MatchExpr &expr) {} + virtual void visit (HIR::AwaitExpr &expr) {} + virtual void visit (HIR::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (HIR::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (HIR::LifetimeWhereClauseItem &item) {} + virtual void visit (HIR::TypeBoundWhereClauseItem &item) {} + virtual void visit (HIR::Method &method) {} + virtual void visit (HIR::ModuleBodied &module) {} + virtual void visit (HIR::ModuleNoBody &module) {} + virtual void visit (HIR::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (HIR::UseTreeGlob &use_tree) {} + virtual void visit (HIR::UseTreeList &use_tree) {} + virtual void visit (HIR::UseTreeRebind &use_tree) {} + virtual void visit (HIR::UseDeclaration &use_decl) {} + virtual void visit (HIR::Function &function) {} + virtual void visit (HIR::TypeAlias &type_alias) {} + virtual void visit (HIR::StructStruct &struct_item) {} + virtual void visit (HIR::TupleStruct &tuple_struct) {} + virtual void visit (HIR::EnumItem &item) {} + virtual void visit (HIR::EnumItemTuple &item) {} + virtual void visit (HIR::EnumItemStruct &item) {} + virtual void visit (HIR::EnumItemDiscriminant &item) {} + virtual void visit (HIR::Enum &enum_item) {} + virtual void visit (HIR::Union &union_item) {} + virtual void visit (HIR::ConstantItem &const_item) {} + virtual void visit (HIR::StaticItem &static_item) {} + virtual void visit (HIR::TraitItemFunc &item) {} + virtual void visit (HIR::TraitItemMethod &item) {} + virtual void visit (HIR::TraitItemConst &item) {} + virtual void visit (HIR::TraitItemType &item) {} + virtual void visit (HIR::Trait &trait) {} + virtual void visit (HIR::InherentImpl &impl) {} + virtual void visit (HIR::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (HIR::ExternalStaticItem &item) {} + virtual void visit (HIR::ExternalFunctionItem &item) {} + virtual void visit (HIR::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (HIR::MacroMatchFragment &match) {} + virtual void visit (HIR::MacroMatchRepetition &match) {} + virtual void visit (HIR::MacroMatcher &matcher) {} + virtual void visit (HIR::MacroRulesDefinition &rules_def) {} + virtual void visit (HIR::MacroInvocation ¯o_invoc) {} + virtual void visit (HIR::MetaItemPath &meta_item) {} + virtual void visit (HIR::MetaItemSeq &meta_item) {} + virtual void visit (HIR::MetaWord &meta_item) {} + virtual void visit (HIR::MetaNameValueStr &meta_item) {} + virtual void visit (HIR::MetaListPaths &meta_item) {} + virtual void visit (HIR::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (HIR::LiteralPattern &pattern) {} + virtual void visit (HIR::IdentifierPattern &pattern) {} + virtual void visit (HIR::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (HIR::RangePatternBoundLiteral &bound) {} + virtual void visit (HIR::RangePatternBoundPath &bound) {} + virtual void visit (HIR::RangePatternBoundQualPath &bound) {} + virtual void visit (HIR::RangePattern &pattern) {} + virtual void visit (HIR::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (HIR::StructPatternFieldTuplePat &field) {} + virtual void visit (HIR::StructPatternFieldIdentPat &field) {} + virtual void visit (HIR::StructPatternFieldIdent &field) {} + virtual void visit (HIR::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (HIR::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (HIR::TupleStructItemsRange &tuple_items) {} + virtual void visit (HIR::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (HIR::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (HIR::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (HIR::TuplePattern &pattern) {} + virtual void visit (HIR::GroupedPattern &pattern) {} + virtual void visit (HIR::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (HIR::EmptyStmt &stmt) {} + virtual void visit (HIR::LetStmt &stmt) {} + virtual void visit (HIR::ExprStmtWithoutBlock &stmt) {} + virtual void visit (HIR::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (HIR::TraitBound &bound) {} + virtual void visit (HIR::ImplTraitType &type) {} + virtual void visit (HIR::TraitObjectType &type) {} + virtual void visit (HIR::ParenthesisedType &type) {} + virtual void visit (HIR::ImplTraitTypeOneBound &type) {} + virtual void visit (HIR::TraitObjectTypeOneBound &type) {} + virtual void visit (HIR::TupleType &type) {} + virtual void visit (HIR::NeverType &type) {} + virtual void visit (HIR::RawPointerType &type) {} + virtual void visit (HIR::ReferenceType &type) {} + virtual void visit (HIR::ArrayType &type) {} + virtual void visit (HIR::SliceType &type) {} + virtual void visit (HIR::InferredType &type) {} + virtual void visit (HIR::BareFunctionType &type) {} + +protected: + HIRCompileBase (Context *ctx) : ctx (ctx) {} + + Context *get_context () { return ctx; } + + Context *ctx; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_BASE diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h new file mode 100644 index 0000000..f890678 --- /dev/null +++ b/gcc/rust/backend/rust-compile-context.h @@ -0,0 +1,247 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_CONTEXT +#define RUST_COMPILE_CONTEXT + +#include "rust-system.h" +#include "rust-hir-map.h" +#include "rust-name-resolver.h" +#include "rust-hir-type-check.h" +#include "rust-backend.h" +#include "rust-compile-tyty.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Compile { + +struct fncontext +{ + ::Bfunction *fndecl; + ::Bvariable *ret_addr; +}; + +class Context +{ +public: + Context (::Backend *backend) + : backend (backend), resolver (Resolver::Resolver::get ()), + tyctx (Resolver::TypeCheckContext::get ()), + mappings (Analysis::Mappings::get ()) + { + // insert the builtins + auto builtins = resolver->get_builtin_types (); + for (auto it = builtins.begin (); it != builtins.end (); it++) + { + HirId ref; + rust_assert ( + tyctx->lookup_type_by_node_id ((*it)->get_node_id (), &ref)); + + TyTy::TyBase *lookup; + rust_assert (tyctx->lookup_type (ref, &lookup)); + + auto compiled = TyTyCompile::compile (backend, lookup); + compiled_type_map[ref] = compiled; + } + } + + ~Context () {} + + bool lookup_compiled_types (HirId id, ::Btype **type) + { + auto it = compiled_type_map.find (id); + if (it == compiled_type_map.end ()) + return false; + + *type = it->second; + return true; + } + + void insert_compiled_type (HirId id, ::Btype *type) + { + compiled_type_map[id] = type; + } + + ::Backend *get_backend () { return backend; } + Resolver::Resolver *get_resolver () { return resolver; } + Resolver::TypeCheckContext *get_tyctx () { return tyctx; } + Analysis::Mappings *get_mappings () { return mappings; } + + void push_block (Bblock *scope) + { + scope_stack.push_back (scope); + statements.push_back ({}); + } + + Bblock *pop_block () + { + auto block = scope_stack.back (); + scope_stack.pop_back (); + + auto stmts = statements.back (); + statements.pop_back (); + + backend->block_add_statements (block, stmts); + + return block; + } + + Bblock *peek_enclosing_scope () + { + if (scope_stack.size () == 0) + return nullptr; + + return scope_stack.back (); + } + + void add_statement (Bstatement *stmt) { statements.back ().push_back (stmt); } + + void insert_var_decl (HirId id, ::Bvariable *decl) + { + compiled_var_decls[id] = decl; + } + + bool lookup_var_decl (HirId id, ::Bvariable **decl) + { + auto it = compiled_var_decls.find (id); + if (it == compiled_var_decls.end ()) + return false; + + *decl = it->second; + return true; + } + + void insert_function_decl (HirId id, ::Bfunction *fn) + { + compiled_fn_map[id] = fn; + } + + bool lookup_function_decl (HirId id, ::Bfunction **fn) + { + auto it = compiled_fn_map.find (id); + if (it == compiled_fn_map.end ()) + return false; + + *fn = it->second; + return true; + } + + void push_fn (::Bfunction *fn, ::Bvariable *ret_addr) + { + fn_stack.push_back (fncontext{fn, ret_addr}); + } + void pop_fn () { fn_stack.pop_back (); } + fncontext peek_fn () { return fn_stack.back (); } + + void push_type (::Btype *t) { type_decls.push_back (t); } + void push_var (::Bvariable *v) { var_decls.push_back (v); } + void push_const (::Bexpression *c) { const_decls.push_back (c); } + void push_function (::Bfunction *f) { func_decls.push_back (f); } + + void write_to_backend () + { + backend->write_global_definitions (type_decls, const_decls, func_decls, + var_decls); + } + + bool function_completed (Bfunction *fn) + { + for (auto it = func_decls.begin (); it != func_decls.end (); it++) + { + Bfunction *i = (*it); + if (i == fn) + { + return true; + } + } + return false; + } + +private: + ::Backend *backend; + Resolver::Resolver *resolver; + Resolver::TypeCheckContext *tyctx; + Analysis::Mappings *mappings; + + // state + std::vector<fncontext> fn_stack; + std::map<HirId, ::Bvariable *> compiled_var_decls; + std::map<HirId, ::Btype *> compiled_type_map; + std::map<HirId, ::Bfunction *> compiled_fn_map; + std::vector< ::std::vector<Bstatement *> > statements; + std::vector< ::Bblock *> scope_stack; + + // To GCC middle-end + std::vector< ::Btype *> type_decls; + std::vector< ::Bvariable *> var_decls; + std::vector< ::Bexpression *> const_decls; + std::vector< ::Bfunction *> func_decls; +}; + +class TyTyResolveCompile : public TyTy::TyVisitor +{ +public: + static ::Btype *compile (Context *ctx, TyTy::TyBase *ty) + { + TyTyResolveCompile compiler (ctx); + ty->accept_vis (compiler); + return compiler.translated; + } + + virtual ~TyTyResolveCompile () {} + + void visit (TyTy::FnType &type) { gcc_unreachable (); } + + void visit (TyTy::BoolType &type) + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + + void visit (TyTy::IntType &type) + { + printf ("type [%s] has ref: %u\n", type.as_string ().c_str (), + type.get_ref ()); + + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + + void visit (TyTy::UintType &type) + { + ::Btype *compiled_type = nullptr; + bool ok = ctx->lookup_compiled_types (type.get_ref (), &compiled_type); + rust_assert (ok); + translated = compiled_type; + } + +private: + TyTyResolveCompile (Context *ctx) : ctx (ctx) {} + + Context *ctx; + ::Btype *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_CONTEXT diff --git a/gcc/rust/backend/rust-compile-expr.h b/gcc/rust/backend/rust-compile-expr.h new file mode 100644 index 0000000..7808af2 --- /dev/null +++ b/gcc/rust/backend/rust-compile-expr.h @@ -0,0 +1,285 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_EXPR +#define RUST_COMPILE_EXPR + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" +#include "rust-compile-resolve-path.h" + +namespace Rust { +namespace Compile { + +class CompileExpr : public HIRCompileBase +{ +public: + static Bexpression *Compile (HIR::Expr *expr, Context *ctx) + { + CompileExpr compiler (ctx); + expr->accept_vis (compiler); + return compiler.translated; + } + + virtual ~CompileExpr () {} + + void visit (HIR::ReturnExpr &expr) + { + Bexpression *compiled_expr + = CompileExpr::Compile (expr.return_expr.get (), ctx); + rust_assert (compiled_expr != nullptr); + + auto fncontext = ctx->peek_fn (); + + std::vector<Bexpression *> retstmts; + retstmts.push_back (compiled_expr); + auto s = ctx->get_backend ()->return_statement (fncontext.fndecl, retstmts, + expr.get_locus ()); + ctx->add_statement (s); + } + + void visit (HIR::CallExpr &expr) + { + Bexpression *fn = ResolvePath::Compile (expr.get_fnexpr (), ctx); + rust_assert (fn != nullptr); + + std::vector<Bexpression *> args; + expr.iterate_params ([&] (HIR::Expr *p) mutable -> bool { + Bexpression *compiled_expr = CompileExpr::Compile (p, ctx); + rust_assert (compiled_expr != nullptr); + args.push_back (compiled_expr); + return true; + }); + + auto fncontext = ctx->peek_fn (); + translated + = ctx->get_backend ()->call_expression (fncontext.fndecl, fn, args, + nullptr, expr.get_locus ()); + } + + void visit (HIR::IdentifierExpr &expr) + { + // need to look up the reference for this identifier + NodeId ref_node_id; + if (!ctx->get_resolver ()->lookup_resolved_name ( + expr.get_mappings ().get_nodeid (), &ref_node_id)) + { + rust_fatal_error (expr.get_locus (), "failed to look up resolved name"); + return; + } + + printf ("have ast node id %u ref %u for expr [%s]\n", + expr.get_mappings ().get_nodeid (), ref_node_id, + expr.as_string ().c_str ()); + + // these ref_node_ids will resolve to a pattern declaration but we are + // interested in the definition that this refers to get the parent id + Resolver::Definition def; + if (!ctx->get_resolver ()->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), "unknown reference"); + return; + } + + HirId ref; + if (!ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), def.parent, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + return; + } + + Bvariable *var = nullptr; + if (!ctx->lookup_var_decl (ref, &var)) + { + rust_fatal_error (expr.get_locus (), + "failed to lookup compiled variable"); + return; + } + + translated = ctx->get_backend ()->var_expression (var, expr.get_locus ()); + } + + void visit (HIR::LiteralExpr &expr) + { + switch (expr.get_lit_type ()) + { + case HIR::Literal::BOOL: { + bool bval = expr.as_string ().compare ("true") == 0; + translated = ctx->get_backend ()->boolean_constant_expression (bval); + } + return; + + case HIR::Literal::INT: { + mpz_t ival; + if (mpz_init_set_str (ival, expr.as_string ().c_str (), 10) != 0) + { + rust_fatal_error (expr.get_locus (), "bad number in literal"); + return; + } + + TyTy::TyBase *tyty = nullptr; + if (!ctx->get_tyctx ()->lookup_type ( + expr.get_mappings ().get_hirid (), &tyty)) + { + rust_fatal_error (expr.get_locus (), + "did not resolve type for this literal expr"); + return; + } + + Btype *type = TyTyResolveCompile::compile (ctx, tyty); + translated + = ctx->get_backend ()->integer_constant_expression (type, ival); + } + return; + + default: + rust_fatal_error (expr.get_locus (), "unknown literal"); + return; + } + + gcc_unreachable (); + } + + void visit (HIR::AssignmentExpr &expr) + { + fncontext fn = ctx->peek_fn (); + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + + Bstatement *assignment + = ctx->get_backend ()->assignment_statement (fn.fndecl, lhs, rhs, + expr.get_locus ()); + ctx->add_statement (assignment); + } + + void visit (HIR::ArithmeticOrLogicalExpr &expr) + { + Operator op; + switch (expr.get_expr_type ()) + { + case HIR::ArithmeticOrLogicalExpr::ADD: + op = OPERATOR_PLUS; + break; + case HIR::ArithmeticOrLogicalExpr::SUBTRACT: + op = OPERATOR_MINUS; + break; + case HIR::ArithmeticOrLogicalExpr::MULTIPLY: + op = OPERATOR_MULT; + break; + case HIR::ArithmeticOrLogicalExpr::DIVIDE: + op = OPERATOR_DIV; + break; + case HIR::ArithmeticOrLogicalExpr::MODULUS: + op = OPERATOR_MOD; + break; + case HIR::ArithmeticOrLogicalExpr::BITWISE_AND: + op = OPERATOR_AND; + break; + case HIR::ArithmeticOrLogicalExpr::BITWISE_OR: + op = OPERATOR_OR; + break; + case HIR::ArithmeticOrLogicalExpr::BITWISE_XOR: + op = OPERATOR_XOR; + break; + case HIR::ArithmeticOrLogicalExpr::LEFT_SHIFT: + op = OPERATOR_LSHIFT; + break; + case HIR::ArithmeticOrLogicalExpr::RIGHT_SHIFT: + op = OPERATOR_RSHIFT; + break; + default: + rust_fatal_error (expr.get_locus (), "failed to compile operator"); + return; + } + + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + + translated = ctx->get_backend ()->binary_expression (op, lhs, rhs, + expr.get_locus ()); + } + + void visit (HIR::ComparisonExpr &expr) + { + Operator op; + switch (expr.get_expr_type ()) + { + case HIR::ComparisonExpr::EQUAL: + op = OPERATOR_EQEQ; + break; + case HIR::ComparisonExpr::NOT_EQUAL: + op = OPERATOR_NOTEQ; + break; + case HIR::ComparisonExpr::GREATER_THAN: + op = OPERATOR_GT; + break; + case HIR::ComparisonExpr::LESS_THAN: + op = OPERATOR_LT; + break; + case HIR::ComparisonExpr::GREATER_OR_EQUAL: + op = OPERATOR_GE; + break; + case HIR::ComparisonExpr::LESS_OR_EQUAL: + op = OPERATOR_LE; + break; + default: + rust_fatal_error (expr.get_locus (), "failed to compile operator"); + return; + } + + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + + translated = ctx->get_backend ()->binary_expression (op, lhs, rhs, + expr.get_locus ()); + } + + void visit (HIR::LazyBooleanExpr &expr) + { + Operator op; + switch (expr.get_expr_type ()) + { + case HIR::LazyBooleanExpr::LOGICAL_OR: + op = OPERATOR_OROR; + break; + case HIR::LazyBooleanExpr::LOGICAL_AND: + op = OPERATOR_ANDAND; + break; + default: + rust_fatal_error (expr.get_locus (), "failed to compile operator"); + return; + } + + auto lhs = CompileExpr::Compile (expr.get_lhs (), ctx); + auto rhs = CompileExpr::Compile (expr.get_rhs (), ctx); + + translated = ctx->get_backend ()->binary_expression (op, lhs, rhs, + expr.get_locus ()); + } + +private: + CompileExpr (Context *ctx) : HIRCompileBase (ctx), translated (nullptr) {} + + Bexpression *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_EXPR diff --git a/gcc/rust/backend/rust-compile-item.h b/gcc/rust/backend/rust-compile-item.h new file mode 100644 index 0000000..dd07435 --- /dev/null +++ b/gcc/rust/backend/rust-compile-item.h @@ -0,0 +1,180 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_ITEM +#define RUST_COMPILE_ITEM + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" +#include "rust-compile-var-decl.h" +#include "rust-compile-stmt.h" + +namespace Rust { +namespace Compile { + +class CompileItem : public HIRCompileBase +{ +public: + static void compile (HIR::Item *item, Context *ctx) + { + CompileItem compiler (ctx); + item->accept_vis (compiler); + } + + virtual ~CompileItem () {} + + void visit (HIR::Function &function) + { + // items can be forward compiled which means we may not need to invoke this + // code + Bfunction *lookup = nullptr; + if (ctx->lookup_function_decl (function.get_mappings ().get_hirid (), + &lookup)) + { + // has this been added to the list then it must be finished + if (ctx->function_completed (lookup)) + { + printf ("returning early the function [%s] is completed!\n", + function.as_string ().c_str ()); + return; + } + } + + TyTy::TyBase *fnType; + if (!ctx->get_tyctx ()->lookup_type (function.get_mappings ().get_hirid (), + &fnType)) + { + rust_fatal_error (function.locus, "failed to lookup function type"); + return; + } + + // convert to the actual function type + auto compiled_fn_type = TyTyCompile::compile (ctx->get_backend (), fnType); + + Bfunction *fndecl + = ctx->get_backend ()->function (compiled_fn_type, function.function_name, + "" /* asm_name */, 0 /* flags */, + function.get_locus ()); + ctx->insert_function_decl (function.get_mappings ().get_hirid (), fndecl); + + // setup the params + TyTy::TyBase *tyret = TyTyExtractRetFromFnType::compile (fnType); + std::vector<TyTy::ParamType *> typarams + = TyTyExtractParamsFromFnType::compile (fnType); + std::vector<Bvariable *> param_vars; + + for (auto &it : typarams) + { + auto compiled_param + = TyTyCompileParam::compile (ctx->get_backend (), fndecl, it); + param_vars.push_back (compiled_param); + + ctx->insert_var_decl (it->get_ref (), compiled_param); + } + + if (!ctx->get_backend ()->function_set_parameters (fndecl, param_vars)) + { + rust_fatal_error (function.get_locus (), + "failed to setup parameter variables"); + return; + } + + // lookup locals + auto block_expr = function.function_body.get (); + auto body_mappings = block_expr->get_mappings (); + + Resolver::Rib *rib = nullptr; + if (!ctx->get_resolver ()->find_name_rib (body_mappings.get_nodeid (), + &rib)) + { + rust_fatal_error (function.get_locus (), + "failed to setup locals per block"); + return; + } + + std::vector<Bvariable *> locals; + rib->iterate_decls ([&] (NodeId n) mutable -> bool { + Resolver::Definition d; + bool ok = ctx->get_resolver ()->lookup_definition (n, &d); + rust_assert (ok); + + HIR::Stmt *decl = nullptr; + ok = ctx->get_mappings ()->resolve_nodeid_to_stmt (d.parent, &decl); + rust_assert (ok); + + Bvariable *compiled = CompileVarDecl::compile (fndecl, decl, ctx); + locals.push_back (compiled); + + return true; + }); + + Bblock *enclosing_scope = ctx->peek_enclosing_scope (); + HIR::BlockExpr *function_body = function.function_body.get (); + + Location start_location = function_body->get_locus (); + Location end_location = function_body->get_closing_locus (); + + Bblock *code_block + = ctx->get_backend ()->block (fndecl, enclosing_scope, locals, + start_location, end_location); + ctx->push_block (code_block); + + Bvariable *return_address = nullptr; + if (function.has_function_return_type ()) + { + Btype *return_type = TyTyCompile::compile (ctx->get_backend (), tyret); + + bool address_is_taken = false; + Bstatement *ret_var_stmt = nullptr; + + return_address = ctx->get_backend ()->temporary_variable ( + fndecl, code_block, return_type, NULL, address_is_taken, + function.get_locus (), &ret_var_stmt); + + ctx->add_statement (ret_var_stmt); + } + + ctx->push_fn (fndecl, return_address); + + // compile the block + function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { + CompileStmt::Compile (s, ctx); + return true; + }); + + ctx->pop_block (); + auto body = ctx->get_backend ()->block_statement (code_block); + if (!ctx->get_backend ()->function_set_body (fndecl, body)) + { + rust_error_at (function.get_locus (), "failed to set body to function"); + return; + } + + ctx->pop_fn (); + + ctx->push_function (fndecl); + } + +private: + CompileItem (Context *ctx) : HIRCompileBase (ctx) {} +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_ITEM diff --git a/gcc/rust/backend/rust-compile-resolve-path.cc b/gcc/rust/backend/rust-compile-resolve-path.cc new file mode 100644 index 0000000..e6683fa --- /dev/null +++ b/gcc/rust/backend/rust-compile-resolve-path.cc @@ -0,0 +1,81 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-linemap.h" +#include "rust-backend.h" +#include "rust-compile-resolve-path.h" +#include "rust-compile-item.h" + +namespace Rust { +namespace Compile { + +void +ResolvePath::visit (HIR::PathInExpression &expr) +{ + // need to look up the reference for this identifier + NodeId ref_node_id; + if (!ctx->get_resolver ()->lookup_resolved_name ( + expr.get_mappings ().get_nodeid (), &ref_node_id)) + { + rust_fatal_error (expr.get_locus (), "failed to look up resolved name"); + return; + } + + printf ("PATHIN have ast node id %u ref %u for expr [%s]\n", + expr.get_mappings ().get_nodeid (), ref_node_id, + expr.as_string ().c_str ()); + + HirId ref; + if (!ctx->get_mappings ()->lookup_node_to_hir ( + expr.get_mappings ().get_crate_num (), ref_node_id, &ref)) + { + rust_fatal_error (expr.get_locus (), "reverse lookup failure"); + return; + } + + // assumes paths are functions for now + Bfunction *fn; + if (!ctx->lookup_function_decl (ref, &fn)) + { + printf ( + "path failed to lookup function attempting to forward resolve!\n"); + + // this might fail because its a forward decl so we can attempt to + // resolve it now + HIR::Item *resolved_item = ctx->get_mappings ()->lookup_hir_item ( + expr.get_mappings ().get_crate_num (), ref); + if (resolved_item == nullptr) + { + rust_fatal_error (expr.get_locus (), "failed to lookup forward decl"); + return; + } + + CompileItem::compile (resolved_item, ctx); + if (!ctx->lookup_function_decl (ref, &fn)) + { + rust_fatal_error (expr.get_locus (), "forward decl was not compiled"); + return; + } + } + + resolved + = ctx->get_backend ()->function_code_expression (fn, expr.get_locus ()); +} + +} // namespace Compile +} // namespace Rust diff --git a/gcc/rust/backend/rust-compile-resolve-path.h b/gcc/rust/backend/rust-compile-resolve-path.h new file mode 100644 index 0000000..d8f393d --- /dev/null +++ b/gcc/rust/backend/rust-compile-resolve-path.h @@ -0,0 +1,52 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_RESOLVE_PATH +#define RUST_COMPILE_RESOLVE_PATH + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" + +namespace Rust { +namespace Compile { + +class ResolvePath : public HIRCompileBase +{ +public: + static Bexpression *Compile (HIR::Expr *expr, Context *ctx) + { + ResolvePath resolver (ctx); + expr->accept_vis (resolver); + rust_assert (resolver.resolved != nullptr); + return resolver.resolved; + } + + virtual ~ResolvePath () {} + + void visit (HIR::PathInExpression &expr); + +private: + ResolvePath (Context *ctx) : HIRCompileBase (ctx), resolved (nullptr) {} + + Bexpression *resolved; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_RESOLVE_PATH diff --git a/gcc/rust/backend/rust-compile-stmt.h b/gcc/rust/backend/rust-compile-stmt.h new file mode 100644 index 0000000..0a08130 --- /dev/null +++ b/gcc/rust/backend/rust-compile-stmt.h @@ -0,0 +1,85 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_STMT +#define RUST_COMPILE_STMT + +#include "rust-compile-base.h" +#include "rust-compile-tyty.h" +#include "rust-compile-expr.h" + +namespace Rust { +namespace Compile { + +class CompileStmt : public HIRCompileBase +{ +public: + static void Compile (HIR::Stmt *stmt, Context *ctx) + { + CompileStmt compiler (ctx); + stmt->accept_vis (compiler); + rust_assert (compiler.ok); + } + + virtual ~CompileStmt () {} + + void visit (HIR::ExprStmtWithoutBlock &stmt) + { + ok = true; + auto translated = CompileExpr::Compile (stmt.get_expr (), ctx); + + // these can be null + if (translated == nullptr) + return; + + gcc_unreachable (); + } + + void visit (HIR::LetStmt &stmt) + { + // marks that the statement has been looked at + ok = true; + + // nothing to do + if (!stmt.has_init_expr ()) + return; + + Bvariable *var = nullptr; + if (!ctx->lookup_var_decl (stmt.get_mappings ().get_hirid (), &var)) + { + rust_fatal_error (stmt.get_locus (), + "failed to lookup compiled variable decl"); + return; + } + + auto *init = CompileExpr::Compile (stmt.get_init_expr (), ctx); + auto fnctx = ctx->peek_fn (); + auto s = ctx->get_backend ()->init_statement (fnctx.fndecl, var, init); + ctx->add_statement (s); + } + +private: + CompileStmt (Context *ctx) : HIRCompileBase (ctx), ok (false) {} + + bool ok; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_STMT diff --git a/gcc/rust/backend/rust-compile-tyty.h b/gcc/rust/backend/rust-compile-tyty.h new file mode 100644 index 0000000..66d2472 --- /dev/null +++ b/gcc/rust/backend/rust-compile-tyty.h @@ -0,0 +1,247 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_TYTY +#define RUST_COMPILE_TYTY + +#include "rust-system.h" +#include "rust-location.h" +#include "rust-diagnostics.h" +#include "rust-backend.h" +#include "rust-tyty.h" +#include "rust-tyty-visitor.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace Compile { + +class TyTyCompile : public TyTy::TyVisitor +{ +public: + static ::Btype *compile (::Backend *backend, TyTy::TyBase *ty) + { + TyTyCompile compiler (backend); + ty->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + return compiler.translated; + } + + ~TyTyCompile () {} + + void visit (TyTy::InferType &type) override + { + // there shouldn't be any of these left + gcc_unreachable (); + } + + void visit (TyTy::UnitType &type) override {} + + void visit (TyTy::FnType &type) override + { + Backend::Btyped_identifier receiver; + std::vector<Backend::Btyped_identifier> parameters; + std::vector<Backend::Btyped_identifier> results; + + if (!type.get_return_type ()->is_unit ()) + { + auto hir_type = type.get_return_type (); + auto ret = TyTyCompile::compile (backend, hir_type); + results.push_back (Backend::Btyped_identifier ( + "_", ret, mappings->lookup_location (hir_type->get_ref ()))); + } + + for (size_t i = 0; i < type.num_params (); i++) + { + auto param_tyty = type.param_at (i); + auto compiled_param_type + = TyTyCompile::compile (backend, param_tyty->get_base_type ()); + auto compiled_param = Backend::Btyped_identifier ( + param_tyty->get_identifier (), compiled_param_type, + mappings->lookup_location (param_tyty->get_ref ())); + + parameters.push_back (compiled_param); + } + + translated + = backend->function_type (receiver, parameters, results, NULL, + mappings->lookup_location (type.get_ref ())); + } + + void visit (TyTy::ParamType &type) override {} + + void visit (TyTy::BoolType &type) override + { + translated = backend->named_type ("bool", backend->bool_type (), + Linemap::predeclared_location ()); + } + + void visit (TyTy::IntType &type) override + { + switch (type.get_kind ()) + { + case TyTy::IntType::I8: + translated + = backend->named_type ("i8", backend->integer_type (false, 8), + Linemap::predeclared_location ()); + return; + + case TyTy::IntType::I16: + translated + = backend->named_type ("i16", backend->integer_type (false, 16), + Linemap::predeclared_location ()); + return; + + case TyTy::IntType::I32: + translated + = backend->named_type ("i32", backend->integer_type (false, 32), + Linemap::predeclared_location ()); + return; + } + gcc_unreachable (); + } + + void visit (TyTy::UintType &type) override + { + switch (type.get_kind ()) + { + case TyTy::UintType::U8: + translated = backend->named_type ("i8", backend->integer_type (true, 8), + Linemap::predeclared_location ()); + return; + + case TyTy::UintType::U16: + translated + = backend->named_type ("i16", backend->integer_type (true, 16), + Linemap::predeclared_location ()); + return; + + case TyTy::UintType::U32: + translated + = backend->named_type ("i32", backend->integer_type (true, 32), + Linemap::predeclared_location ()); + return; + } + gcc_unreachable (); + } + +private: + TyTyCompile (::Backend *backend) + : backend (backend), translated (nullptr), + mappings (Analysis::Mappings::get ()) + {} + + ::Backend *backend; + ::Btype *translated; + Analysis::Mappings *mappings; +}; + +class TyTyExtractParamsFromFnType : public TyTy::TyVisitor +{ +public: + static std::vector<TyTy::ParamType *> compile (TyTy::TyBase *ty) + { + TyTyExtractParamsFromFnType compiler; + ty->accept_vis (compiler); + rust_assert (compiler.ok); + return compiler.translated; + } + + ~TyTyExtractParamsFromFnType () {} + + void visit (TyTy::FnType &type) override + { + ok = true; + for (size_t i = 0; i < type.num_params (); i++) + { + translated.push_back (type.param_at (i)); + } + } + +private: + TyTyExtractParamsFromFnType () : ok (false) {} + + bool ok; + std::vector<TyTy::ParamType *> translated; +}; + +class TyTyExtractRetFromFnType : public TyTy::TyVisitor +{ +public: + static TyTy::TyBase *compile (TyTy::TyBase *ty) + { + TyTyExtractRetFromFnType compiler; + ty->accept_vis (compiler); + rust_assert (compiler.ok); + return compiler.translated; + } + + ~TyTyExtractRetFromFnType () {} + + void visit (TyTy::FnType &type) override + { + ok = true; + translated = type.get_return_type (); + } + +private: + TyTyExtractRetFromFnType () : ok (false), translated (nullptr) {} + + bool ok; + TyTy::TyBase *translated; +}; + +class TyTyCompileParam : public TyTy::TyVisitor +{ +public: + static ::Bvariable *compile (::Backend *backend, Bfunction *fndecl, + TyTy::TyBase *ty) + { + TyTyCompileParam compiler (backend, fndecl); + ty->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + return compiler.translated; + } + + ~TyTyCompileParam () {} + + void visit (TyTy::ParamType &type) override + { + auto btype = TyTyCompile::compile (backend, type.get_base_type ()); + bool tree_addressable = false; + translated = backend->parameter_variable (fndecl, type.get_identifier (), + btype, tree_addressable, + mappings->lookup_location ( + type.get_ref ())); + } + +private: + TyTyCompileParam (::Backend *backend, ::Bfunction *fndecl) + : backend (backend), translated (nullptr), fndecl (fndecl), + mappings (Analysis::Mappings::get ()) + {} + + ::Backend *backend; + ::Bvariable *translated; + ::Bfunction *fndecl; + Analysis::Mappings *mappings; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_TYTY diff --git a/gcc/rust/backend/rust-compile-var-decl.h b/gcc/rust/backend/rust-compile-var-decl.h new file mode 100644 index 0000000..be3141a --- /dev/null +++ b/gcc/rust/backend/rust-compile-var-decl.h @@ -0,0 +1,69 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_COMPILE_VAR_DECL +#define RUST_COMPILE_VAR_DECL + +#include "rust-compile-base.h" + +namespace Rust { +namespace Compile { + +class CompileVarDecl : public HIRCompileBase +{ +public: + static ::Bvariable *compile (::Bfunction *fndecl, HIR::Stmt *stmt, + Context *ctx) + { + CompileVarDecl compiler (ctx, fndecl); + stmt->accept_vis (compiler); + rust_assert (compiler.translated != nullptr); + ctx->insert_var_decl (stmt->get_mappings ().get_hirid (), + compiler.translated); + return compiler.translated; + } + + virtual ~CompileVarDecl () {} + + void visit (HIR::LetStmt &stmt) + { + TyTy::TyBase *resolved_type = nullptr; + bool ok = ctx->get_tyctx ()->lookup_type (stmt.get_mappings ().get_hirid (), + &resolved_type); + rust_assert (ok); + + ::Btype *translated_type = TyTyResolveCompile::compile (ctx, resolved_type); + + translated = ctx->get_backend ()->local_variable ( + fndecl, stmt.get_pattern ()->as_string (), translated_type, + NULL /*decl_var*/, false /*address_taken*/, stmt.get_locus ()); + } + +private: + CompileVarDecl (Context *ctx, ::Bfunction *fndecl) + : HIRCompileBase (ctx), fndecl (fndecl), translated (nullptr) + {} + + ::Bfunction *fndecl; + ::Bvariable *translated; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_VAR_DECL diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 300240f..11c380b 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -1,1501 +1,47 @@ -#include "rust-compile.h" -#include "rust-diagnostics.h" - -namespace Rust { -namespace Compile { - -#define VISIT_POP(L, S, R, B) \ - do \ - { \ - auto before = B.size (); \ - S->accept_vis (*this); \ - if (B.size () <= before) \ - break; \ - R = B.back (); \ - B.pop_back (); \ - } \ - while (0) - -Compilation::Compilation (AST::Crate &crate, ::Backend *backend) - : crate (crate), backend (backend), scope (backend) -{} - -Compilation::~Compilation () {} - -bool -Compilation::Compile (AST::Crate &crate, ::Backend *backend) -{ - Compilation resolver (crate, backend); - return resolver.go (); -} - -bool -Compilation::go () -{ - scope.Push (); - - // builtin primitives - scope.InsertType ("bool", - backend->named_type ("bool", backend->bool_type (), - Linemap::predeclared_location ())); - scope.InsertType ("i64", - backend->named_type ("i64", - backend->integer_type (false, 64), - Linemap::predeclared_location ())); - scope.InsertType ("i32", - backend->named_type ("i32", - backend->integer_type (false, 32), - Linemap::predeclared_location ())); - scope.InsertType ("i16", - backend->named_type ("i16", - backend->integer_type (false, 16), - Linemap::predeclared_location ())); - scope.InsertType ("i8", - backend->named_type ("i8", backend->integer_type (false, 8), - Linemap::predeclared_location ())); - scope.InsertType ("u64", - backend->named_type ("u64", - backend->integer_type (true, 64), - Linemap::predeclared_location ())); - scope.InsertType ("u32", - backend->named_type ("u32", - backend->integer_type (true, 32), - Linemap::predeclared_location ())); - scope.InsertType ("u16", - backend->named_type ("u16", - backend->integer_type (true, 16), - Linemap::predeclared_location ())); - scope.InsertType ("u8", - backend->named_type ("u8", backend->integer_type (true, 8), - Linemap::predeclared_location ())); - scope.InsertType ("f64", backend->float_type (64)); - scope.InsertType ("f32", backend->float_type (32)); - - for (auto &item : crate.items) - item->accept_vis (*this); - scope.Pop (); - - // Define all globally declared values. - if (saw_errors ()) - return false; - - backend->write_global_definitions (type_decls, const_decls, func_decls, - var_decls); - return true; -} - -bool -Compilation::compileVarDecl (Bfunction *fndecl, AST::LetStmt *stmt, - std::vector<Bvariable *> &vars) -{ - AST::Type *type = stmt->has_type () ? stmt->get_type ().get () : stmt->inferedType; - translatedType = NULL; - type->accept_vis (*this); - if (translatedType == NULL) - { - rust_error_at (stmt->get_locus (), "failed to compile type for var decl"); - return false; - } - - stmt->get_pattern ()->accept_vis (*this); - for (auto &pattern : patternBuffer) - { - auto var = backend->local_variable (fndecl, pattern.get_ident (), - translatedType, NULL /*decl_var*/, - false /*address_taken*/, stmt->get_locus ()); - vars.push_back (var); - scope.InsertVar (pattern.get_ident (), var); - } - patternBuffer.clear (); - return true; -} - -Bexpression * -Compilation::compileBooleanLiteral (std::string val) -{ - bool bval = val.compare ("true") == 0; - return backend->boolean_constant_expression (bval); -} - -Bexpression * -Compilation::compileFloatLiteral (std::string val, Location locus) -{ - Btype *type = NULL; - bool ok = scope.LookupType ("f32", &type); - if (!ok) - { - rust_fatal_error (locus, "unable to find type"); - return NULL; - } - mpfr_t fval; - if (mpfr_init_set_str (fval, val.c_str (), 10, GMP_RNDN) != 0) - { - rust_fatal_error (locus, "bad number in literal"); - return NULL; - } - return backend->float_constant_expression (type, fval); -} - -Bexpression * -Compilation::compileIntegerLiteral (std::string val, Location locus) -{ - Btype *type = NULL; - bool ok = scope.LookupType ("i32", &type); - if (!ok) - { - rust_fatal_error (locus, "unable to find type"); - return NULL; - } - mpz_t ival; - if (mpz_init_set_str (ival, val.c_str (), 10) != 0) - { - rust_fatal_error (locus, "bad number in literal"); - return NULL; - } - return backend->integer_constant_expression (type, ival); -} - -void -Compilation::visit (AST::Token &tok) -{} - -void -Compilation::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -Compilation::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -Compilation::visit (AST::IdentifierExpr &ident_expr) -{ - Bvariable *var = NULL; - if (!scope.LookupVar (ident_expr.as_string (), &var)) - { - rust_fatal_error (ident_expr.get_locus (), "unknown var"); - return; - } - exprs.push_back (backend->var_expression (var, ident_expr.get_locus ())); -} - -void -Compilation::visit (AST::Lifetime &lifetime) -{} - -void -Compilation::visit (AST::LifetimeParam &lifetime_param) -{} - -void -Compilation::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -Compilation::visit (AST::PathInExpression &path) -{ - Bfunction *fn = NULL; - if (scope.LookupFunction (path.as_string (), &fn)) - { - auto expr - = backend->function_code_expression (fn, path.get_locus ()); - exprs.push_back (expr); - translatedType = scope.GetFnRetType (fn); - return; - } -} - -void -Compilation::visit (AST::TypePathSegment &segment) -{} -void -Compilation::visit (AST::TypePathSegmentGeneric &segment) -{} -void -Compilation::visit (AST::TypePathSegmentFunction &segment) -{} - -void -Compilation::visit (AST::TypePath &path) -{ - if (path.get_segments ().size () > 1) - { - rust_error_at (path.get_locus (), "unable to compile multi segment types yet"); - return; - } - - Btype *type = NULL; - if (!scope.LookupType (path.as_string (), &type)) - { - rust_error_at (path.get_locus (), "unknown type"); - return; - } - translatedType = type; -} - -void -Compilation::visit (AST::QualifiedPathInExpression &path) -{} -void -Compilation::visit (AST::QualifiedPathInType &path) -{} - -// rust-expr.h -void -Compilation::visit (AST::LiteralExpr &expr) -{ - Bexpression *compiled; - switch (expr.get_lit_type ()) - { - case AST::Literal::BOOL: - compiled = compileBooleanLiteral (expr.as_string ()); - break; - - case AST::Literal::FLOAT: - compiled - = compileFloatLiteral (expr.as_string (), expr.get_locus ()); - break; - - case AST::Literal::INT: - compiled - = compileIntegerLiteral (expr.as_string (), expr.get_locus ()); - break; - - default: - rust_fatal_error (expr.get_locus (), "unknown literal"); - return; - } - - exprs.push_back (compiled); -} - -void -Compilation::visit (AST::AttrInputLiteral &attr_input) -{} -void -Compilation::visit (AST::MetaItemLitExpr &meta_item) -{} -void -Compilation::visit (AST::MetaItemPathLit &meta_item) -{} -void -Compilation::visit (AST::BorrowExpr &expr) -{} -void -Compilation::visit (AST::DereferenceExpr &expr) -{} -void -Compilation::visit (AST::ErrorPropagationExpr &expr) -{} - -void -Compilation::visit (AST::NegationExpr &expr) -{ - Bexpression *root = NULL; - VISIT_POP (expr.get_negated_expr ()->get_locus_slow (), expr.get_negated_expr ().get (), root, - exprs); - if (root == NULL) - { - rust_error_at (expr.get_negated_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Operator op; - switch (expr.get_negation_type ()) - { - case AST::NegationExpr::NEGATE: - op = OPERATOR_MINUS; - break; - case AST::NegationExpr::NOT: - op = OPERATOR_NOT; - break; - default: - rust_fatal_error (expr.get_locus (), "failed to compile operator"); - return; - } - - auto unary = backend->unary_expression (op, root, expr.get_locus ()); - exprs.push_back (unary); -} - -void -Compilation::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - Bexpression *lhs = NULL; - VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); - if (lhs == NULL) - { - rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Bexpression *rhs = NULL; - VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); - if (rhs == NULL) - { - rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Operator op; - switch (expr.get_expr_type ()) - { - case AST::ArithmeticOrLogicalExpr::ADD: - op = OPERATOR_PLUS; - break; - case AST::ArithmeticOrLogicalExpr::SUBTRACT: - op = OPERATOR_MINUS; - break; - case AST::ArithmeticOrLogicalExpr::MULTIPLY: - op = OPERATOR_MULT; - break; - case AST::ArithmeticOrLogicalExpr::DIVIDE: - op = OPERATOR_DIV; - break; - case AST::ArithmeticOrLogicalExpr::MODULUS: - op = OPERATOR_MOD; - break; - case AST::ArithmeticOrLogicalExpr::BITWISE_AND: - op = OPERATOR_AND; - break; - case AST::ArithmeticOrLogicalExpr::BITWISE_OR: - op = OPERATOR_OR; - break; - case AST::ArithmeticOrLogicalExpr::BITWISE_XOR: - op = OPERATOR_XOR; - break; - case AST::ArithmeticOrLogicalExpr::LEFT_SHIFT: - op = OPERATOR_LSHIFT; - break; - case AST::ArithmeticOrLogicalExpr::RIGHT_SHIFT: - op = OPERATOR_RSHIFT; - break; - default: - rust_fatal_error (expr.get_locus (), "failed to compile operator"); - return; - } - - auto binExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); - exprs.push_back (binExpr); -} - -void -Compilation::visit (AST::ComparisonExpr &expr) -{ - Bexpression *lhs = NULL; - VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); - if (lhs == NULL) - { - rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Bexpression *rhs = NULL; - VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); - if (rhs == NULL) - { - rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Operator op; - switch (expr.get_expr_type ()) - { - case AST::ComparisonExpr::EQUAL: - op = OPERATOR_EQEQ; - break; - case AST::ComparisonExpr::NOT_EQUAL: - op = OPERATOR_NOTEQ; - break; - case AST::ComparisonExpr::GREATER_THAN: - op = OPERATOR_GT; - break; - case AST::ComparisonExpr::LESS_THAN: - op = OPERATOR_LT; - break; - case AST::ComparisonExpr::GREATER_OR_EQUAL: - op = OPERATOR_GE; - break; - case AST::ComparisonExpr::LESS_OR_EQUAL: - op = OPERATOR_LE; - break; - default: - rust_fatal_error (expr.get_locus (), "failed to compile operator"); - return; - } - - auto compExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); - exprs.push_back (compExpr); -} - -void -Compilation::visit (AST::LazyBooleanExpr &expr) -{ - Bexpression *lhs = NULL; - VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); - if (lhs == NULL) - { - rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Bexpression *rhs = NULL; - VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); - if (rhs == NULL) - { - rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Operator op; - switch (expr.get_expr_type ()) - { - case AST::LazyBooleanExpr::LOGICAL_OR: - op = OPERATOR_OROR; - break; - case AST::LazyBooleanExpr::LOGICAL_AND: - op = OPERATOR_ANDAND; - break; - default: - rust_fatal_error (expr.get_locus (), "failed to compile operator"); - return; - } - - auto compExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); - exprs.push_back (compExpr); -} - -void -Compilation::visit (AST::TypeCastExpr &expr) -{} - -void -Compilation::visit (AST::AssignmentExpr &expr) -{ - Bexpression *lhs = NULL; - VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); - if (lhs == NULL) - { - rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Bexpression *rhs = NULL; - VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); - if (rhs == NULL) - { - rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - auto s = backend->assignment_statement (scope.GetCurrentFndecl (), lhs, rhs, - expr.get_locus ()); - scope.AddStatement (s); -} - -void -Compilation::visit (AST::CompoundAssignmentExpr &expr) -{} -void -Compilation::visit (AST::GroupedExpr &expr) -{} - -void -Compilation::visit (AST::ArrayElemsValues &elems) -{ - std::vector< ::Bexpression *> elements; - - bool failed = false; - elems.iterate ([&] (AST::Expr *expr) mutable -> bool { - Bexpression *value = nullptr; - VISIT_POP (expr.get_locus_slow (), expr, value, exprs); - if (value == nullptr) - { - rust_fatal_error (expr->get_locus_slow (), - "failed to compile value to array initialiser"); - return false; - } - elements.push_back (value); - return true; - }); - - // nothing to do when its failed - if (failed) - return; - - arrayConsStack.push_back (elements); -} - -void -Compilation::visit (AST::ArrayElemsCopied &elems) -{} - -void -Compilation::visit (AST::ArrayExpr &expr) -{ - translatedType = nullptr; - expr.get_inferred_type ()->accept_vis (*this); - if (translatedType == nullptr) - { - rust_error_at (expr.get_locus_slow (), - "failed to compile array type for ArrayExpr"); - return; - } - - ::Btype *compiledType = translatedType; - translatedType = nullptr; - - auto before = arrayConsStack.size (); - expr.get_array_elems ()->accept_vis (*this); - if (arrayConsStack.size () <= before) - { - rust_error_at (expr.get_locus_slow (), - "failed to compile the array constructor"); - return; - } - std::vector< ::Bexpression *> initializer = arrayConsStack.back (); - arrayConsStack.pop_back (); - - std::vector<unsigned long> indexes; - for (unsigned long i = 0; i < initializer.size (); ++i) - indexes.push_back (i); - - Bexpression *cons - = backend->array_constructor_expression (compiledType, indexes, initializer, - expr.get_locus_slow ()); - exprs.push_back (cons); -} - -void -Compilation::visit (AST::ArrayIndexExpr &expr) -{ - Bexpression *arrayExpr = nullptr; - VISIT_POP (expr.get_array_expr ()->get_locus_slow (), expr.get_array_expr (), - arrayExpr, exprs); - if (arrayExpr == nullptr) - { - rust_error_at (expr.get_locus_slow (), - "failed to compile value to array expression reference"); - return; - } - - Bexpression *indexExpr = nullptr; - VISIT_POP (expr.get_index_expr ()->get_locus_slow (), expr.get_index_expr (), - indexExpr, exprs); - if (indexExpr == nullptr) - { - rust_error_at (expr.get_locus_slow (), - "failed to compile value to array index expression"); - return; - } - - Bexpression *indexExpression - = backend->array_index_expression (arrayExpr, indexExpr, - expr.get_locus_slow ()); - exprs.push_back (indexExpression); -} - -void -Compilation::visit (AST::TupleExpr &expr) -{} -void -Compilation::visit (AST::TupleIndexExpr &expr) -{} -void -Compilation::visit (AST::StructExprStruct &expr) -{} -// void Compilation::visit(StructExprField& field) {} -void -Compilation::visit (AST::StructExprFieldIdentifier &field) -{} - -void -Compilation::visit (AST::StructExprFieldIdentifierValue &field) -{ - Bexpression *value = NULL; - VISIT_POP (field.get_value ()->get_locus_slow (), field.get_value ().get (), value, exprs); - if (value == NULL) - { - rust_fatal_error (field.get_value ()->get_locus_slow (), - "failed to compile value to struct"); - return; - } - exprs.push_back (value); -} - -void -Compilation::visit (AST::StructExprFieldIndexValue &field) -{ - Bexpression *value = NULL; - VISIT_POP (field.get_value ()->get_locus_slow (), field.get_value ().get (), value, exprs); - if (value == NULL) - { - rust_fatal_error (field.get_value ()->get_locus_slow (), - "failed to compile value to struct"); - return; - } - exprs.push_back (value); -} - -void -Compilation::visit (AST::StructExprStructFields &expr) -{ - AST::StructStruct *decl = NULL; - if (!scope.LookupStructDecl (expr.get_struct_name ().as_string (), &decl)) - { - rust_error_at (expr.get_locus (), "unknown type"); - return; - } - - Btype *structType = NULL; - if (!scope.LookupType (expr.get_struct_name ().as_string (), &structType)) - { - rust_fatal_error (expr.get_locus (), "unknown type"); - return; - } - - structBuffer.push_back (decl); - std::vector<Bexpression *> constructor; - - // FIXME type resolution pass should ensures these are in correct order - // and have defaults if required - for (auto &field : expr.get_fields ()) - { - Bexpression *value = NULL; - VISIT_POP (expr.get_locus (), field, value, exprs); - if (value == NULL) - { - rust_fatal_error (expr.get_locus (), - "failed to compile value to struct"); - return; - } - - constructor.push_back (value); - } - - structBuffer.pop_back (); - auto cons = backend->constructor_expression (structType, constructor, - expr.get_locus ()); - exprs.push_back (cons); -} - -void -Compilation::visit (AST::StructExprStructBase &expr) -{} -void -Compilation::visit (AST::StructExprTuple &expr) -{} -void -Compilation::visit (AST::StructExprUnit &expr) -{} -// void Compilation::visit(EnumExprField& field) {} -void -Compilation::visit (AST::EnumExprFieldIdentifier &field) -{} -void -Compilation::visit (AST::EnumExprFieldIdentifierValue &field) -{} -void -Compilation::visit (AST::EnumExprFieldIndexValue &field) -{} -void -Compilation::visit (AST::EnumExprStruct &expr) -{} -void -Compilation::visit (AST::EnumExprTuple &expr) -{} -void -Compilation::visit (AST::EnumExprFieldless &expr) -{} - -void -Compilation::visit (AST::CallExpr &expr) -{ - Bexpression *fn = NULL; - VISIT_POP (expr.get_function_expr ()->get_locus_slow (), expr.get_function_expr (), fn, exprs); - if (fn == NULL) - { - rust_error_at (expr.get_function_expr ()->get_locus_slow (), "failed to resolve"); - return; - } - - std::vector<Bexpression *> args; - for (auto ¶m : expr.get_params ()) - { - Bexpression *arg = NULL; - VISIT_POP (param->get_locus_slow (), param, arg, exprs); - if (arg == NULL) - { - rust_error_at (param->get_locus_slow (), - "failed to compile argument"); - return; - } - - args.push_back (arg); - } - - auto call = backend->call_expression (scope.GetCurrentFndecl (), fn, args, - NULL, expr.get_locus ()); - exprs.push_back (call); -} - -void -Compilation::visit (AST::MethodCallExpr &expr) -{} -void -Compilation::visit (AST::FieldAccessExpr &expr) -{} -void -Compilation::visit (AST::ClosureExprInner &expr) -{} - -void -Compilation::visit (AST::BlockExpr &expr) -{ - Bblock *enclosingScope = NULL; - Location start_location; /* = stmt.locus; FIXME */ - Location end_location; // FIXME - - std::vector<Bvariable *> vars; - auto code_block - = backend->block (scope.GetCurrentFndecl (), scope.CurBlock (), vars, - start_location, end_location); - - scope.PushBlock (code_block); - for (auto &stmt : expr.get_statements ()) - { - stmt->accept_vis (*this); - } - // dont pop -} - -void -Compilation::visit (AST::ClosureExprInnerTyped &expr) -{} -void -Compilation::visit (AST::ContinueExpr &expr) -{} -void -Compilation::visit (AST::BreakExpr &expr) -{} -void -Compilation::visit (AST::RangeFromToExpr &expr) -{} -void -Compilation::visit (AST::RangeFromExpr &expr) -{} -void -Compilation::visit (AST::RangeToExpr &expr) -{} -void -Compilation::visit (AST::RangeFullExpr &expr) -{} -void -Compilation::visit (AST::RangeFromToInclExpr &expr) -{} -void -Compilation::visit (AST::RangeToInclExpr &expr) -{} - -void -Compilation::visit (AST::ReturnExpr &expr) -{ - Bexpression *ret = NULL; - VISIT_POP (expr.get_returned_expr ()->get_locus_slow (), expr.get_returned_expr ().get (), ret, exprs); - if (ret == NULL) - { - rust_fatal_error (expr.get_returned_expr ()->get_locus_slow (), - "failed to compile"); - return; - } - - std::vector<Bexpression *> retstmts; - retstmts.push_back (ret); - auto s = backend->return_statement (scope.GetCurrentFndecl (), retstmts, - expr.get_locus ()); - scope.AddStatement (s); -} - -void -Compilation::visit (AST::UnsafeBlockExpr &expr) -{} - -void -Compilation::visit (AST::LoopExpr &expr) -{} - -void -Compilation::visit (AST::WhileLoopExpr &expr) -{} - -void -Compilation::visit (AST::WhileLetLoopExpr &expr) -{} -void -Compilation::visit (AST::ForLoopExpr &expr) -{} - -void -Compilation::visit (AST::IfExpr &expr) -{ - Bexpression *cond = NULL; - VISIT_POP (expr.get_condition_expr ()->get_locus_slow (), - expr.get_condition_expr ().get (), cond, exprs); - if (cond == NULL) - { - rust_error_at (expr.get_condition_expr ()->get_locus_slow (), - "failed to compile"); - return; - } - - expr.vis_if_block (*this); - Bblock *then_block = scope.PopBlock (); - - auto stmt = backend->if_statement (scope.GetCurrentFndecl (), cond, - then_block, NULL, expr.get_locus ()); - stmts.push_back (stmt); -} - -void -Compilation::visit (AST::IfExprConseqElse &expr) -{ - Bexpression *cond = NULL; - VISIT_POP (expr.get_condition_expr ()->get_locus_slow (), - expr.get_condition_expr ().get (), cond, exprs); - if (cond == NULL) - { - rust_error_at (expr.get_condition_expr ()->get_locus_slow (), - "failed to compile"); - return; - } - - expr.vis_if_block (*this); - Bblock *then_block = scope.PopBlock (); - - expr.vis_else_block (*this); - Bblock *else_block = scope.PopBlock (); - - auto stmt - = backend->if_statement (scope.GetCurrentFndecl (), cond, then_block, - else_block, expr.get_locus ()); - stmts.push_back (stmt); -} - -void -Compilation::visit (AST::IfExprConseqIf &expr) -{ - Bexpression *cond = NULL; - VISIT_POP (expr.get_condition_expr ()->get_locus_slow (), - expr.get_condition_expr ().get (), cond, exprs); - if (cond == NULL) - { - rust_error_at (expr.get_condition_expr ()->get_locus_slow (), - "failed to compile"); - return; - } - - expr.vis_if_block (*this); - Bblock *then_block = scope.PopBlock (); - - // setup else block - Bblock *enclosingScope = NULL; - Location start_location; /* = stmt.locus; FIXME */ - Location end_location; // FIXME - - std::vector<Bvariable *> vars; - auto else_block - = backend->block (scope.GetCurrentFndecl (), scope.CurBlock (), vars, - start_location, end_location); - - scope.PushBlock (else_block); - expr.vis_conseq_if_expr (*this); - // get trailing if required - for (auto &s : stmts) - scope.AddStatement (s); - stmts.clear (); - scope.PopBlock (); - - auto stmt - = backend->if_statement (scope.GetCurrentFndecl (), cond, then_block, - else_block, expr.get_locus ()); - stmts.push_back (stmt); -} - -void -Compilation::visit (AST::IfExprConseqIfLet &expr) -{ - printf ("IfExprConseqIfLet %s\n", expr.as_string ().c_str ()); -} -void -Compilation::visit (AST::IfLetExpr &expr) -{ - printf ("IfLetExpr %s\n", expr.as_string ().c_str ()); -} -void -Compilation::visit (AST::IfLetExprConseqElse &expr) -{ - printf ("IfLetExprConseqElse %s\n", expr.as_string ().c_str ()); -} - -void -Compilation::visit (AST::IfLetExprConseqIf &expr) -{ - printf ("IfLetExprConseqIf %s\n", expr.as_string ().c_str ()); -} - -void -Compilation::visit (AST::IfLetExprConseqIfLet &expr) -{ - printf ("IfLetExprConseqIfLet %s\n", expr.as_string ().c_str ()); -} - -// void Compilation::visit(MatchCase& match_case) {} -/*void -Compilation::visit (AST::MatchCaseBlockExpr &match_case) -{}*/ -/*void -Compilation::visit (AST::MatchCaseExpr &match_case) -{}*/ -void -Compilation::visit (AST::MatchExpr &expr) -{} -void -Compilation::visit (AST::AwaitExpr &expr) -{} -void -Compilation::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -Compilation::visit (AST::TypeParam ¶m) -{} -// void Compilation::visit(WhereClauseItem& item) {} -void -Compilation::visit (AST::LifetimeWhereClauseItem &item) -{} -void -Compilation::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -Compilation::visit (AST::Method &method) -{} -void -Compilation::visit (AST::ModuleBodied &module) -{} -void -Compilation::visit (AST::ModuleNoBody &module) -{} -void -Compilation::visit (AST::ExternCrate &crate) -{} -// void Compilation::visit(UseTree& use_tree) {} -void -Compilation::visit (AST::UseTreeGlob &use_tree) -{} -void -Compilation::visit (AST::UseTreeList &use_tree) -{} -void -Compilation::visit (AST::UseTreeRebind &use_tree) -{} -void -Compilation::visit (AST::UseDeclaration &use_decl) -{} - -void -Compilation::visit (AST::Function &function) -{ - Backend::Btyped_identifier receiver; - std::vector<Backend::Btyped_identifier> parameters; - std::vector<Backend::Btyped_identifier> results; - - for (auto ¶m : function.get_function_params ()) - { - // translate the type - translatedType = NULL; - param.get_type ()->accept_vis (*this); - if (translatedType == NULL) - { - rust_error_at (param.get_locus (), "failed to generate type for parameter"); - return; - } - - auto before = patternBuffer.size (); - param.get_pattern ()->accept_vis (*this); - if (patternBuffer.size () <= before) - { - rust_error_at (param.get_locus (), "failed to analyse parameter name"); - return; - } - - auto numParamsPerType = patternBuffer.size () - before; - for (size_t i = 0; i < numParamsPerType; i++) - { - auto paramName = patternBuffer.back (); - patternBuffer.pop_back (); - parameters.push_back ( - Backend::Btyped_identifier (paramName.get_ident (), - translatedType, param.get_locus ())); - } - } - - Btype *returnType = NULL; - if (function.has_return_type ()) - { - translatedType = NULL; - function.get_return_type ()->accept_vis (*this); - if (translatedType == NULL) - { - rust_fatal_error (function.get_locus (), - "failed to generate type for function"); - return; - } - returnType = translatedType; - - // add into the results: - results.push_back ( - Backend::Btyped_identifier ("_", translatedType, Location ())); - } +// Copyright (C) 2020 Free Software Foundation, Inc. - Btype *fntype = backend->function_type (receiver, parameters, results, NULL, - function.get_locus ()); - Bfunction *fndecl - = backend->function (fntype, function.get_function_name (), "" /* asm_name */, - 0 /* flags */, function.get_locus ()); +// This file is part of GCC. - scope.InsertFunction (function.get_function_name (), fndecl, returnType); - scope.Push (); +// 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. - // setup the params - std::vector<Bvariable *> param_vars; - for (auto ¶m : parameters) - { - bool tree_addressable = false; - auto p = backend->parameter_variable (fndecl, param.name, param.btype, - tree_addressable, param.location); +// 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. - scope.InsertVar (param.name, p); - param_vars.push_back (p); - } +// 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/>. - if (!backend->function_set_parameters (fndecl, param_vars)) - { - rust_error_at (function.get_locus (), "failed to setup parameter variables"); - return; - } - - std::vector<Bvariable *> vars; - for (auto &decl : function.locals) - { - if (!compileVarDecl (fndecl, decl, vars)) - { - rust_error_at (decl->get_locus (), "failed to compile var decl"); - return; - } - } - - // is null for top level functions - nested functions will have an enclosing - // scope - Bblock *enclosingScope = NULL; - Location start_location = function.get_locus (); - Location end_location; - if (function.get_definition ()->get_statements ().size () > 0) - { - end_location - = function.get_definition ()->get_statements ().back ()->get_locus_slow (); - } - - auto code_block = backend->block (fndecl, enclosingScope, vars, - start_location, end_location); - - scope.PushBlock (code_block); - - Bvariable *retDecl = NULL; - if (function.has_return_type ()) - { - bool address_is_taken = false; - Bstatement *ret_var_stmt = NULL; - retDecl = backend->temporary_variable (fndecl, code_block, returnType, - NULL, address_is_taken, - function.get_locus (), &ret_var_stmt); - scope.AddStatement (ret_var_stmt); - } - scope.PushCurrentFunction (function.get_function_name (), fndecl, returnType, - retDecl); - - for (auto &stmt : function.get_definition ()->get_statements ()) - stmt->accept_vis (*this); - - scope.PopBlock (); - - auto body = backend->block_statement (code_block); - if (!backend->function_set_body (fndecl, body)) - { - rust_error_at (function.get_locus (), "failed to set body to function"); - return; - } - - scope.Pop (); - scope.PopCurrentFunction (); - - func_decls.push_back (fndecl); -} - -void -Compilation::visit (AST::TypeAlias &type_alias) -{} - -void -Compilation::visit (AST::StructStruct &struct_item) -{ - std::vector<Backend::Btyped_identifier> fields; - for (auto &field : struct_item.get_fields ()) - { - translatedType = NULL; - field.get_field_type ()->accept_vis (*this); - if (translatedType == NULL) - { - rust_fatal_error ( - struct_item.get_locus () /* StructField is mi sing locus */, - "failed to compile struct field"); - return; - } - - fields.push_back (Backend::Btyped_identifier ( - field.get_field_name (), translatedType, - struct_item.get_locus () /* StructField is mi sing locus */)); - } - - auto compiledStruct - = backend->placeholder_struct_type (struct_item.get_struct_name (), - struct_item.get_locus ()); - bool ok = backend->set_placeholder_struct_type (compiledStruct, fields); - if (!ok) - { - rust_fatal_error (struct_item.get_locus (), "failed to compile struct"); - return; - } - - type_decls.push_back (compiledStruct); - scope.InsertType (struct_item.get_struct_name (), compiledStruct); - scope.InsertStructDecl (struct_item.get_struct_name (), &struct_item); -} - -void -Compilation::visit (AST::TupleStruct &tuple_struct) -{} -void -Compilation::visit (AST::EnumItem &item) -{} -void -Compilation::visit (AST::EnumItemTuple &item) -{} -void -Compilation::visit (AST::EnumItemStruct &item) -{} -void -Compilation::visit (AST::EnumItemDiscriminant &item) -{} -void -Compilation::visit (AST::Enum &enum_item) -{} -void -Compilation::visit (AST::Union &union_item) -{} -void -Compilation::visit (AST::ConstantItem &const_item) -{} -void -Compilation::visit (AST::StaticItem &static_item) -{} -void -Compilation::visit (AST::TraitItemFunc &item) -{} -void -Compilation::visit (AST::TraitItemMethod &item) -{} -void -Compilation::visit (AST::TraitItemConst &item) -{} -void -Compilation::visit (AST::TraitItemType &item) -{} -void -Compilation::visit (AST::Trait &trait) -{} -void -Compilation::visit (AST::InherentImpl &impl) -{} -void -Compilation::visit (AST::TraitImpl &impl) -{} -// void Compilation::visit(ExternalItem& item) {} -void -Compilation::visit (AST::ExternalStaticItem &item) -{} -void -Compilation::visit (AST::ExternalFunctionItem &item) -{} -void -Compilation::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -Compilation::visit (AST::MacroMatchFragment &match) -{} -void -Compilation::visit (AST::MacroMatchRepetition &match) -{} -void -Compilation::visit (AST::MacroMatcher &matcher) -{} -void -Compilation::visit (AST::MacroRulesDefinition &rules_def) -{} -void -Compilation::visit (AST::MacroInvocation ¯o_invoc) -{} -void -Compilation::visit (AST::MetaItemPath &meta_item) -{} -void -Compilation::visit (AST::MetaItemSeq &meta_item) -{} -void -Compilation::visit (AST::MetaWord &meta_item) -{} -void -Compilation::visit (AST::MetaNameValueStr &meta_item) -{} -void -Compilation::visit (AST::MetaListPaths &meta_item) -{} -void -Compilation::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -Compilation::visit (AST::LiteralPattern &pattern) -{ - printf ("LiteralPattern: %s\n", pattern.as_string ().c_str ()); -} - -void -Compilation::visit (AST::IdentifierPattern &pattern) -{ - patternBuffer.push_back (pattern); -} +#include "rust-compile.h" +#include "rust-compile-item.h" -void -Compilation::visit (AST::WildcardPattern &pattern) -{} -// void Compilation::visit(RangePatternBound& bound) {} -void -Compilation::visit (AST::RangePatternBoundLiteral &bound) -{} -void -Compilation::visit (AST::RangePatternBoundPath &bound) -{} -void -Compilation::visit (AST::RangePatternBoundQualPath &bound) -{} -void -Compilation::visit (AST::RangePattern &pattern) -{} -void -Compilation::visit (AST::ReferencePattern &pattern) -{} -// void Compilation::visit(StructPatternField& field) {} -void -Compilation::visit (AST::StructPatternFieldTuplePat &field) -{} -void -Compilation::visit (AST::StructPatternFieldIdentPat &field) -{} -void -Compilation::visit (AST::StructPatternFieldIdent &field) -{} -void -Compilation::visit (AST::StructPattern &pattern) -{} -// void Compilation::visit(TupleStructItems& tuple_items) {} -void -Compilation::visit (AST::TupleStructItemsNoRange &tuple_items) -{} -void -Compilation::visit (AST::TupleStructItemsRange &tuple_items) -{} -void -Compilation::visit (AST::TupleStructPattern &pattern) -{} -// void Compilation::visit(TuplePatternItems& tuple_items) {} -void -Compilation::visit (AST::TuplePatternItemsMultiple &tuple_items) -{} -void -Compilation::visit (AST::TuplePatternItemsRanged &tuple_items) -{} -void -Compilation::visit (AST::TuplePattern &pattern) -{} -void -Compilation::visit (AST::GroupedPattern &pattern) -{} -void -Compilation::visit (AST::SlicePattern &pattern) -{} +namespace Rust { +namespace Compile { -// rust-stmt.h -void -Compilation::visit (AST::EmptyStmt &stmt) +CompileCrate::CompileCrate (HIR::Crate &crate, Context *ctx) + : crate (crate), ctx (ctx) {} -void - -Compilation::visit (AST::LetStmt &stmt) -{ - if (!stmt.has_init_expr ()) - return; - - stmt.get_pattern ()->accept_vis (*this); - for (auto &pattern : patternBuffer) - { - Bvariable *var = NULL; - if (!scope.LookupVar (pattern.get_ident (), &var)) - { - rust_error_at (stmt.get_locus (), "failed to find var decl for %s", - pattern.get_ident ().c_str ()); - return; - } - - varBuffer.push_back (var); - - Bexpression *init = NULL; - VISIT_POP (stmt.get_init_expr ()->get_locus_slow (), stmt.get_init_expr (), init, - exprs); - if (init == NULL) - { - rust_error_at (stmt.get_init_expr ()->get_locus_slow (), - "failed to compile init statement"); - return; - } - auto s = backend->init_statement (scope.GetCurrentFndecl (), var, init); - scope.AddStatement (s); - - varBuffer.pop_back (); - } - patternBuffer.clear (); -} +CompileCrate::~CompileCrate () {} void -Compilation::visit (AST::ExprStmtWithoutBlock &stmt) -{ - stmt.get_expr ()->accept_vis (*this); -} +CompileCrate::Compile (HIR::Crate &crate, Context *ctx) -void -Compilation::visit (AST::ExprStmtWithBlock &stmt) { - Bblock *enclosingScope = NULL; - Location start_location; /* = stmt.locus; FIXME */ - Location end_location; // FIXME - - std::vector<Bvariable *> vars; - auto code_block - = backend->block (scope.GetCurrentFndecl (), scope.CurBlock (), vars, - start_location, end_location); - - scope.PushBlock (code_block); - stmt.get_expr ()->accept_vis (*this); - - // get trailing if required - for (auto &s : stmts) - { - scope.AddStatement (s); - } - stmts.clear (); - - scope.PopBlock (); - - auto body = backend->block_statement (code_block); - scope.AddStatement (body); + CompileCrate c (crate, ctx); + c.go (); } -// rust-type.h -void -Compilation::visit (AST::TraitBound &bound) -{} -void -Compilation::visit (AST::ImplTraitType &type) -{} -void -Compilation::visit (AST::TraitObjectType &type) -{} -void -Compilation::visit (AST::ParenthesisedType &type) -{} -void -Compilation::visit (AST::ImplTraitTypeOneBound &type) -{} -void -Compilation::visit (AST::TraitObjectTypeOneBound &type) -{} -void -Compilation::visit (AST::TupleType &type) -{} -void -Compilation::visit (AST::NeverType &type) -{} -void -Compilation::visit (AST::RawPointerType &type) -{} -void -Compilation::visit (AST::ReferenceType &type) -{} - void -Compilation::visit (AST::ArrayType &type) +CompileCrate::go () { - Btype *elementType; - translatedType = nullptr; - type.get_elem_type ()->accept_vis (*this); - if (translatedType == nullptr) - { - rust_error_at (type.get_locus (), - "Failed to compile element type for array"); - return; - } - elementType = translatedType; - - Bexpression *length = nullptr; - VISIT_POP (type.get_size_expr ()->get_locus_slow (), type.get_size_expr (), - length, exprs); - if (length == nullptr) - { - rust_error_at (type.get_size_expr ()->get_locus_slow (), - "failed to size for array type"); - return; - } - - translatedType = backend->array_type (elementType, length); + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + CompileItem::compile (it->get (), ctx); } -void -Compilation::visit (AST::SliceType &type) -{} -void -Compilation::visit (AST::InferredType &type) -{} -void -Compilation::visit (AST::BareFunctionType &type) -{} - } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile.h b/gcc/rust/backend/rust-compile.h index 88c8318..18f3e54 100644 --- a/gcc/rust/backend/rust-compile.h +++ b/gcc/rust/backend/rust-compile.h @@ -1,257 +1,47 @@ -#pragma once +// Copyright (C) 2020 Free Software Foundation, Inc. -#include "rust-system.h" -#include "rust-ast-full.h" -#include "rust-ast-visitor.h" -#include "rust-backend.h" -#include "cscope.h" +// This file is part of GCC. -namespace Rust { -namespace Compile { +// 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. -class Compilation : public AST::ASTVisitor -{ -public: - static bool Compile (AST::Crate &crate, ::Backend *backend); +// 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. - ~Compilation (); +// 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/>. - // visitor impl - // rust-ast.h - // virtual void visit(AttrInput& attr_input); - // virtual void visit(TokenTree& token_tree); - // virtual void visit(MacroMatch& macro_match); - virtual void visit (AST::Token &tok); - virtual void visit (AST::DelimTokenTree &delim_tok_tree); - virtual void visit (AST::AttrInputMetaItemContainer &input); - // virtual void visit(MetaItem& meta_item); - // virtual void vsit(Stmt& stmt); - // virtual void visit(Expr& expr); - virtual void visit (AST::IdentifierExpr &ident_expr); - // virtual void visit(Pattern& pattern); - // virtual void visit(Type& type); - // virtual void visit(TypeParamBound& type_param_bound); - virtual void visit (AST::Lifetime &lifetime); - // virtual void visit(GenericParam& generic_param); - virtual void visit (AST::LifetimeParam &lifetime_param); - // virtual void visit(TraitItem& trait_item); - // virtual void visit(InherentImplItem& inherent_impl_item); - // virtual void visit(TraitImplItem& trait_impl_item); - virtual void visit (AST::MacroInvocationSemi ¯o); +#ifndef RUST_COMPILE_H +#define RUST_COMPILE_H - // rust-path.h - virtual void visit (AST::PathInExpression &path); - virtual void visit (AST::TypePathSegment &segment); - virtual void visit (AST::TypePathSegmentGeneric &segment); - virtual void visit (AST::TypePathSegmentFunction &segment); - virtual void visit (AST::TypePath &path); - virtual void visit (AST::QualifiedPathInExpression &path); - virtual void visit (AST::QualifiedPathInType &path); - - // rust-expr.h - virtual void visit (AST::LiteralExpr &expr); - virtual void visit (AST::AttrInputLiteral &attr_input); - virtual void visit (AST::MetaItemLitExpr &meta_item); - virtual void visit (AST::MetaItemPathLit &meta_item); - virtual void visit (AST::BorrowExpr &expr); - virtual void visit (AST::DereferenceExpr &expr); - virtual void visit (AST::ErrorPropagationExpr &expr); - virtual void visit (AST::NegationExpr &expr); - virtual void visit (AST::ArithmeticOrLogicalExpr &expr); - virtual void visit (AST::ComparisonExpr &expr); - virtual void visit (AST::LazyBooleanExpr &expr); - virtual void visit (AST::TypeCastExpr &expr); - virtual void visit (AST::AssignmentExpr &expr); - virtual void visit (AST::CompoundAssignmentExpr &expr); - virtual void visit (AST::GroupedExpr &expr); - // virtual void visit(ArrayElems& elems); - virtual void visit (AST::ArrayElemsValues &elems); - virtual void visit (AST::ArrayElemsCopied &elems); - virtual void visit (AST::ArrayExpr &expr); - virtual void visit (AST::ArrayIndexExpr &expr); - virtual void visit (AST::TupleExpr &expr); - virtual void visit (AST::TupleIndexExpr &expr); - virtual void visit (AST::StructExprStruct &expr); - // virtual void visit(StructExprField& field); - virtual void visit (AST::StructExprFieldIdentifier &field); - virtual void visit (AST::StructExprFieldIdentifierValue &field); - virtual void visit (AST::StructExprFieldIndexValue &field); - virtual void visit (AST::StructExprStructFields &expr); - virtual void visit (AST::StructExprStructBase &expr); - virtual void visit (AST::StructExprTuple &expr); - virtual void visit (AST::StructExprUnit &expr); - // virtual void visit(EnumExprField& field); - virtual void visit (AST::EnumExprFieldIdentifier &field); - virtual void visit (AST::EnumExprFieldIdentifierValue &field); - virtual void visit (AST::EnumExprFieldIndexValue &field); - virtual void visit (AST::EnumExprStruct &expr); - virtual void visit (AST::EnumExprTuple &expr); - virtual void visit (AST::EnumExprFieldless &expr); - virtual void visit (AST::CallExpr &expr); - virtual void visit (AST::MethodCallExpr &expr); - virtual void visit (AST::FieldAccessExpr &expr); - virtual void visit (AST::ClosureExprInner &expr); - virtual void visit (AST::BlockExpr &expr); - virtual void visit (AST::ClosureExprInnerTyped &expr); - virtual void visit (AST::ContinueExpr &expr); - virtual void visit (AST::BreakExpr &expr); - virtual void visit (AST::RangeFromToExpr &expr); - virtual void visit (AST::RangeFromExpr &expr); - virtual void visit (AST::RangeToExpr &expr); - virtual void visit (AST::RangeFullExpr &expr); - virtual void visit (AST::RangeFromToInclExpr &expr); - virtual void visit (AST::RangeToInclExpr &expr); - virtual void visit (AST::ReturnExpr &expr); - virtual void visit (AST::UnsafeBlockExpr &expr); - virtual void visit (AST::LoopExpr &expr); - virtual void visit (AST::WhileLoopExpr &expr); - virtual void visit (AST::WhileLetLoopExpr &expr); - virtual void visit (AST::ForLoopExpr &expr); - virtual void visit (AST::IfExpr &expr); - virtual void visit (AST::IfExprConseqElse &expr); - virtual void visit (AST::IfExprConseqIf &expr); - virtual void visit (AST::IfExprConseqIfLet &expr); - virtual void visit (AST::IfLetExpr &expr); - virtual void visit (AST::IfLetExprConseqElse &expr); - virtual void visit (AST::IfLetExprConseqIf &expr); - virtual void visit (AST::IfLetExprConseqIfLet &expr); - // virtual void visit(MatchCase& match_case); - // virtual void visit (AST::MatchCaseBlockExpr &match_case); - // virtual void visit (AST::MatchCaseExpr &match_case); - virtual void visit (AST::MatchExpr &expr); - virtual void visit (AST::AwaitExpr &expr); - virtual void visit (AST::AsyncBlockExpr &expr); - - // rust-item.h - virtual void visit (AST::TypeParam ¶m); - // virtual void visit(WhereClauseItem& item); - virtual void visit (AST::LifetimeWhereClauseItem &item); - virtual void visit (AST::TypeBoundWhereClauseItem &item); - virtual void visit (AST::Method &method); - virtual void visit (AST::ModuleBodied &module); - virtual void visit (AST::ModuleNoBody &module); - virtual void visit (AST::ExternCrate &crate); - // virtual void visit(UseTree& use_tree); - virtual void visit (AST::UseTreeGlob &use_tree); - virtual void visit (AST::UseTreeList &use_tree); - virtual void visit (AST::UseTreeRebind &use_tree); - virtual void visit (AST::UseDeclaration &use_decl); - virtual void visit (AST::Function &function); - virtual void visit (AST::TypeAlias &type_alias); - virtual void visit (AST::StructStruct &struct_item); - virtual void visit (AST::TupleStruct &tuple_struct); - virtual void visit (AST::EnumItem &item); - virtual void visit (AST::EnumItemTuple &item); - virtual void visit (AST::EnumItemStruct &item); - virtual void visit (AST::EnumItemDiscriminant &item); - virtual void visit (AST::Enum &enum_item); - virtual void visit (AST::Union &union_item); - virtual void visit (AST::ConstantItem &const_item); - virtual void visit (AST::StaticItem &static_item); - virtual void visit (AST::TraitItemFunc &item); - virtual void visit (AST::TraitItemMethod &item); - virtual void visit (AST::TraitItemConst &item); - virtual void visit (AST::TraitItemType &item); - virtual void visit (AST::Trait &trait); - virtual void visit (AST::InherentImpl &impl); - virtual void visit (AST::TraitImpl &impl); - // virtual void visit(ExternalItem& item); - virtual void visit (AST::ExternalStaticItem &item); - virtual void visit (AST::ExternalFunctionItem &item); - virtual void visit (AST::ExternBlock &block); - - // rust-macro.h - virtual void visit (AST::MacroMatchFragment &match); - virtual void visit (AST::MacroMatchRepetition &match); - virtual void visit (AST::MacroMatcher &matcher); - virtual void visit (AST::MacroRulesDefinition &rules_def); - virtual void visit (AST::MacroInvocation ¯o_invoc); - virtual void visit (AST::MetaItemPath &meta_item); - virtual void visit (AST::MetaItemSeq &meta_item); - virtual void visit (AST::MetaWord &meta_item); - virtual void visit (AST::MetaNameValueStr &meta_item); - virtual void visit (AST::MetaListPaths &meta_item); - virtual void visit (AST::MetaListNameValueStr &meta_item); +#include "rust-system.h" +#include "rust-hir-full.h" +#include "rust-compile-context.h" - // rust-pattern.h - virtual void visit (AST::LiteralPattern &pattern); - virtual void visit (AST::IdentifierPattern &pattern); - virtual void visit (AST::WildcardPattern &pattern); - // virtual void visit(RangePatternBound& bound); - virtual void visit (AST::RangePatternBoundLiteral &bound); - virtual void visit (AST::RangePatternBoundPath &bound); - virtual void visit (AST::RangePatternBoundQualPath &bound); - virtual void visit (AST::RangePattern &pattern); - virtual void visit (AST::ReferencePattern &pattern); - // virtual void visit(StructPatternField& field); - virtual void visit (AST::StructPatternFieldTuplePat &field); - virtual void visit (AST::StructPatternFieldIdentPat &field); - virtual void visit (AST::StructPatternFieldIdent &field); - virtual void visit (AST::StructPattern &pattern); - // virtual void visit(TupleStructItems& tuple_items); - virtual void visit (AST::TupleStructItemsNoRange &tuple_items); - virtual void visit (AST::TupleStructItemsRange &tuple_items); - virtual void visit (AST::TupleStructPattern &pattern); - // virtual void visit(TuplePatternItems& tuple_items); - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items); - virtual void visit (AST::TuplePatternItemsRanged &tuple_items); - virtual void visit (AST::TuplePattern &pattern); - virtual void visit (AST::GroupedPattern &pattern); - virtual void visit (AST::SlicePattern &pattern); +namespace Rust { +namespace Compile { - // rust-stmt.h - virtual void visit (AST::EmptyStmt &stmt); - virtual void visit (AST::LetStmt &stmt); - virtual void visit (AST::ExprStmtWithoutBlock &stmt); - virtual void visit (AST::ExprStmtWithBlock &stmt); +class CompileCrate +{ +public: + static void Compile (HIR::Crate &crate, Context *ctx); - // rust-type.h - virtual void visit (AST::TraitBound &bound); - virtual void visit (AST::ImplTraitType &type); - virtual void visit (AST::TraitObjectType &type); - virtual void visit (AST::ParenthesisedType &type); - virtual void visit (AST::ImplTraitTypeOneBound &type); - virtual void visit (AST::TraitObjectTypeOneBound &type); - virtual void visit (AST::TupleType &type); - virtual void visit (AST::NeverType &type); - virtual void visit (AST::RawPointerType &type); - virtual void visit (AST::ReferenceType &type); - virtual void visit (AST::ArrayType &type); - virtual void visit (AST::SliceType &type); - virtual void visit (AST::InferredType &type); - virtual void visit (AST::BareFunctionType &type); + ~CompileCrate (); private: - Compilation (AST::Crate &crate, Backend *backend); - bool go (); - - AST::Crate &crate; - Backend *backend; + CompileCrate (HIR::Crate &crate, Context *ctx); + void go (); - // utils - bool compileVarDecl (Bfunction *fndecl, AST::LetStmt *stmt, - std::vector<Bvariable *> &vars); - - Bexpression *compileBooleanLiteral (std::string val); - Bexpression *compileFloatLiteral (std::string val, Location locus); - Bexpression *compileIntegerLiteral (std::string val, Location locus); - - // state - Scope scope; - ::Btype *translatedType; - std::vector<AST::IdentifierPattern> patternBuffer; - std::vector< ::Bexpression *> exprs; - std::vector< ::Bstatement *> stmts; - std::vector< ::Bvariable *> varBuffer; - std::vector<AST::StructStruct *> structBuffer; - std::vector<std::vector< ::Bexpression *> > arrayConsStack; - - // careful these are the vectors we pass into the GCC middle-end - std::vector< ::Btype *> type_decls; - std::vector< ::Bvariable *> var_decls; - std::vector< ::Bexpression *> const_decls; - std::vector< ::Bfunction *> func_decls; + HIR::Crate &crate; + Context *ctx; }; } // namespace Compile } // namespace Rust + +#endif // RUST_COMPILE_H diff --git a/gcc/rust/hir/README.md b/gcc/rust/hir/README.md new file mode 100644 index 0000000..550d104 --- /dev/null +++ b/gcc/rust/hir/README.md @@ -0,0 +1,40 @@ +# GCCRS HIR + +Working with the AST has proved to become difficult. To overcome non lexical scoping +a toplevel scan pass was added to provide lookups for functioins. To get ready for the +gimple conversion pass, type resolution scanned blocks to create the list of locals per +block. Type Conversion had to create awkward getters/setters on LetStmts to have a Type or +InferedType which was more of a hack that what should really be there. ArrayExprs get checked +and create their own type to be checked against a possible LetStmt type. All of these things +started to become hard to manage. + +HIR from the RFC defines how they create lookups and IDs for all the nodes which solves the toplevel +scan pass. The lowering to HIR allows for cleanup in how types are resolved. Without using +the HIR and IDs implementing the shadowing rules was going to become very difficult. + + +## IMPL: + +* AST-lower - move down to HIR classes - generate mappings and IDs + +* Name Resolution - Check for path segments naming and map to HirIDS + This should in theory map for example a call expression to already have the HirID to the function ready + Dyn dispatch may need some help here if its a method the receiver could be bound the local name hirid + the resoltion would need to be fixed up in type resolution pass + +* Expand - Gather locals per block and fix up returns is it possible to generate return expressions + at this pass? + +* Type Resolution - Port over work from AST Type resolver + generate mir from this pass? + + +For now this can then port over to the existing GIMPLE conversion faily easily. But after more +of the core data structures work MIR will be needed for all the glue that will need to be generated. + + +## Returns + +looks like its implemented by an implicit mutable return variable for the function. If were processing +a block expression and the last element on the block is an expression we can try to bind it to the mutable +return variable. diff --git a/gcc/rust/hir/rust-ast-lower-base.h b/gcc/rust/hir/rust-ast-lower-base.h new file mode 100644 index 0000000..093129e --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-base.h @@ -0,0 +1,251 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_LOWER_BASE +#define RUST_AST_LOWER_BASE + +#include "rust-system.h" +#include "rust-ast-full.h" +#include "rust-ast-visitor.h" +#include "rust-hir-map.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace HIR { + +// base class to allow derivatives to overload as needed +class ASTLoweringBase : public AST::ASTVisitor +{ +public: + virtual ~ASTLoweringBase () {} + + // visitor impl + // rust-ast.h + // virtual void visit(AttrInput& attr_input); + // virtual void visit(TokenTree& token_tree); + // virtual void visit(MacroMatch& macro_match); + virtual void visit (AST::Token &tok) {} + virtual void visit (AST::DelimTokenTree &delim_tok_tree) {} + virtual void visit (AST::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // void vsit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (AST::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (AST::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (AST::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (AST::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (AST::PathInExpression &path) {} + virtual void visit (AST::TypePathSegment &segment) {} + virtual void visit (AST::TypePathSegmentGeneric &segment) {} + virtual void visit (AST::TypePathSegmentFunction &segment) {} + virtual void visit (AST::TypePath &path) {} + virtual void visit (AST::QualifiedPathInExpression &path) {} + virtual void visit (AST::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (AST::LiteralExpr &expr) {} + virtual void visit (AST::AttrInputLiteral &attr_input) {} + virtual void visit (AST::MetaItemLitExpr &meta_item) {} + virtual void visit (AST::MetaItemPathLit &meta_item) {} + virtual void visit (AST::BorrowExpr &expr) {} + virtual void visit (AST::DereferenceExpr &expr) {} + virtual void visit (AST::ErrorPropagationExpr &expr) {} + virtual void visit (AST::NegationExpr &expr) {} + virtual void visit (AST::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (AST::ComparisonExpr &expr) {} + virtual void visit (AST::LazyBooleanExpr &expr) {} + virtual void visit (AST::TypeCastExpr &expr) {} + virtual void visit (AST::AssignmentExpr &expr) {} + virtual void visit (AST::CompoundAssignmentExpr &expr) {} + virtual void visit (AST::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (AST::ArrayElemsValues &elems) {} + virtual void visit (AST::ArrayElemsCopied &elems) {} + virtual void visit (AST::ArrayExpr &expr) {} + virtual void visit (AST::ArrayIndexExpr &expr) {} + virtual void visit (AST::TupleExpr &expr) {} + virtual void visit (AST::TupleIndexExpr &expr) {} + virtual void visit (AST::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (AST::StructExprFieldIdentifier &field) {} + virtual void visit (AST::StructExprFieldIdentifierValue &field) {} + virtual void visit (AST::StructExprFieldIndexValue &field) {} + virtual void visit (AST::StructExprStructFields &expr) {} + virtual void visit (AST::StructExprStructBase &expr) {} + virtual void visit (AST::StructExprTuple &expr) {} + virtual void visit (AST::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (AST::EnumExprFieldIdentifier &field) {} + virtual void visit (AST::EnumExprFieldIdentifierValue &field) {} + virtual void visit (AST::EnumExprFieldIndexValue &field) {} + virtual void visit (AST::EnumExprStruct &expr) {} + virtual void visit (AST::EnumExprTuple &expr) {} + virtual void visit (AST::EnumExprFieldless &expr) {} + virtual void visit (AST::CallExpr &expr) {} + virtual void visit (AST::MethodCallExpr &expr) {} + virtual void visit (AST::FieldAccessExpr &expr) {} + virtual void visit (AST::ClosureExprInner &expr) {} + virtual void visit (AST::BlockExpr &expr) {} + virtual void visit (AST::ClosureExprInnerTyped &expr) {} + virtual void visit (AST::ContinueExpr &expr) {} + virtual void visit (AST::BreakExpr &expr) {} + virtual void visit (AST::RangeFromToExpr &expr) {} + virtual void visit (AST::RangeFromExpr &expr) {} + virtual void visit (AST::RangeToExpr &expr) {} + virtual void visit (AST::RangeFullExpr &expr) {} + virtual void visit (AST::RangeFromToInclExpr &expr) {} + virtual void visit (AST::RangeToInclExpr &expr) {} + virtual void visit (AST::ReturnExpr &expr) {} + virtual void visit (AST::UnsafeBlockExpr &expr) {} + virtual void visit (AST::LoopExpr &expr) {} + virtual void visit (AST::WhileLoopExpr &expr) {} + virtual void visit (AST::WhileLetLoopExpr &expr) {} + virtual void visit (AST::ForLoopExpr &expr) {} + virtual void visit (AST::IfExpr &expr) {} + virtual void visit (AST::IfExprConseqElse &expr) {} + virtual void visit (AST::IfExprConseqIf &expr) {} + virtual void visit (AST::IfExprConseqIfLet &expr) {} + virtual void visit (AST::IfLetExpr &expr) {} + virtual void visit (AST::IfLetExprConseqElse &expr) {} + virtual void visit (AST::IfLetExprConseqIf &expr) {} + virtual void visit (AST::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (AST::MatchCaseBlockExpr &match_case) {} + // virtual void visit (AST::MatchCaseExpr &match_case) {} + virtual void visit (AST::MatchExpr &expr) {} + virtual void visit (AST::AwaitExpr &expr) {} + virtual void visit (AST::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (AST::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (AST::LifetimeWhereClauseItem &item) {} + virtual void visit (AST::TypeBoundWhereClauseItem &item) {} + virtual void visit (AST::Method &method) {} + virtual void visit (AST::ModuleBodied &module) {} + virtual void visit (AST::ModuleNoBody &module) {} + virtual void visit (AST::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (AST::UseTreeGlob &use_tree) {} + virtual void visit (AST::UseTreeList &use_tree) {} + virtual void visit (AST::UseTreeRebind &use_tree) {} + virtual void visit (AST::UseDeclaration &use_decl) {} + virtual void visit (AST::Function &function) {} + virtual void visit (AST::TypeAlias &type_alias) {} + virtual void visit (AST::StructStruct &struct_item) {} + virtual void visit (AST::TupleStruct &tuple_struct) {} + virtual void visit (AST::EnumItem &item) {} + virtual void visit (AST::EnumItemTuple &item) {} + virtual void visit (AST::EnumItemStruct &item) {} + virtual void visit (AST::EnumItemDiscriminant &item) {} + virtual void visit (AST::Enum &enum_item) {} + virtual void visit (AST::Union &union_item) {} + virtual void visit (AST::ConstantItem &const_item) {} + virtual void visit (AST::StaticItem &static_item) {} + virtual void visit (AST::TraitItemFunc &item) {} + virtual void visit (AST::TraitItemMethod &item) {} + virtual void visit (AST::TraitItemConst &item) {} + virtual void visit (AST::TraitItemType &item) {} + virtual void visit (AST::Trait &trait) {} + virtual void visit (AST::InherentImpl &impl) {} + virtual void visit (AST::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (AST::ExternalStaticItem &item) {} + virtual void visit (AST::ExternalFunctionItem &item) {} + virtual void visit (AST::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (AST::MacroMatchFragment &match) {} + virtual void visit (AST::MacroMatchRepetition &match) {} + virtual void visit (AST::MacroMatcher &matcher) {} + virtual void visit (AST::MacroRulesDefinition &rules_def) {} + virtual void visit (AST::MacroInvocation ¯o_invoc) {} + virtual void visit (AST::MetaItemPath &meta_item) {} + virtual void visit (AST::MetaItemSeq &meta_item) {} + virtual void visit (AST::MetaWord &meta_item) {} + virtual void visit (AST::MetaNameValueStr &meta_item) {} + virtual void visit (AST::MetaListPaths &meta_item) {} + virtual void visit (AST::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (AST::LiteralPattern &pattern) {} + virtual void visit (AST::IdentifierPattern &pattern) {} + virtual void visit (AST::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (AST::RangePatternBoundLiteral &bound) {} + virtual void visit (AST::RangePatternBoundPath &bound) {} + virtual void visit (AST::RangePatternBoundQualPath &bound) {} + virtual void visit (AST::RangePattern &pattern) {} + virtual void visit (AST::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (AST::StructPatternFieldTuplePat &field) {} + virtual void visit (AST::StructPatternFieldIdentPat &field) {} + virtual void visit (AST::StructPatternFieldIdent &field) {} + virtual void visit (AST::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (AST::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (AST::TupleStructItemsRange &tuple_items) {} + virtual void visit (AST::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (AST::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (AST::TuplePattern &pattern) {} + virtual void visit (AST::GroupedPattern &pattern) {} + virtual void visit (AST::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (AST::EmptyStmt &stmt) {} + virtual void visit (AST::LetStmt &stmt) {} + virtual void visit (AST::ExprStmtWithoutBlock &stmt) {} + virtual void visit (AST::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (AST::TraitBound &bound) {} + virtual void visit (AST::ImplTraitType &type) {} + virtual void visit (AST::TraitObjectType &type) {} + virtual void visit (AST::ParenthesisedType &type) {} + virtual void visit (AST::ImplTraitTypeOneBound &type) {} + virtual void visit (AST::TraitObjectTypeOneBound &type) {} + virtual void visit (AST::TupleType &type) {} + virtual void visit (AST::NeverType &type) {} + virtual void visit (AST::RawPointerType &type) {} + virtual void visit (AST::ReferenceType &type) {} + virtual void visit (AST::ArrayType &type) {} + virtual void visit (AST::SliceType &type) {} + virtual void visit (AST::InferredType &type) {} + virtual void visit (AST::BareFunctionType &type) {} + +protected: + ASTLoweringBase () : mappings (Analysis::Mappings::get ()) {} + + Analysis::Mappings *mappings; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_AST_LOWER_BASE diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h new file mode 100644 index 0000000..50e67a8 --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -0,0 +1,242 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_LOWER_EXPR +#define RUST_AST_LOWER_EXPR + +#include "rust-diagnostics.h" + +#include "rust-ast-lower-base.h" + +namespace Rust { +namespace HIR { + +class ASTLoweringExpr : public ASTLoweringBase +{ +public: + static HIR::Expr *translate (AST::Expr *expr) + { + ASTLoweringExpr resolver; + expr->accept_vis (resolver); + if (resolver.translated != nullptr) + { + resolver.mappings->insert_hir_expr ( + resolver.translated->get_mappings ().get_crate_num (), + resolver.translated->get_mappings ().get_hirid (), + resolver.translated); + } + + return resolver.translated; + } + + virtual ~ASTLoweringExpr () {} + + void visit (AST::PathInExpression &expr) + { + std::vector<HIR::PathExprSegment> path_segments; + expr.iterate_path_segments ([&] (AST::PathExprSegment &s) mutable -> bool { + rust_assert (s.has_generic_args () == false); // TODO + + HIR::PathIdentSegment is (s.get_ident_segment ().as_string ()); + HIR::PathExprSegment seg (is, s.get_locus ()); + path_segments.push_back (seg); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::PathInExpression (mapping, std::move (path_segments), + expr.get_locus (), + expr.opening_scope_resolution ()); + } + + void visit (AST::ReturnExpr &expr) + { + HIR::Expr *return_expr + = expr.has_returned_expr () + ? ASTLoweringExpr::translate (expr.get_returned_expr ().get ()) + : nullptr; + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::ReturnExpr (mapping, expr.get_locus (), + std::unique_ptr<HIR::Expr> (return_expr)); + } + + void visit (AST::CallExpr &expr) + { + std::vector<HIR::Attribute> outer_attribs; + HIR::Expr *func + = ASTLoweringExpr::translate (expr.get_function_expr ().get ()); + std::vector<std::unique_ptr<HIR::Expr> > params; + expr.iterate_params ([&] (AST::Expr *p) mutable -> bool { + auto trans = ASTLoweringExpr::translate (p); + params.push_back (std::unique_ptr<HIR::Expr> (trans)); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping ( + crate_num, UNKNOWN_NODEID /* this can map back to the AST*/, + mappings->get_next_hir_id (crate_num), UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::CallExpr (mapping, std::unique_ptr<HIR::Expr> (func), + std::move (params), std::move (outer_attribs), + expr.get_locus ()); + } + + void visit (AST::AssignmentExpr &expr) + { + HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ()); + HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::AssignmentExpr (mapping, std::unique_ptr<HIR::Expr> (lhs), + std::unique_ptr<HIR::Expr> (rhs), + expr.get_locus ()); + } + + void visit (AST::IdentifierExpr &expr) + { + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + translated + = new HIR::IdentifierExpr (mapping, expr.as_string (), expr.get_locus ()); + } + + void visit (AST::LiteralExpr &expr) + { + HIR::Literal::LitType type = HIR::Literal::LitType::CHAR; + switch (expr.get_lit_type ()) + { + case AST::Literal::LitType::CHAR: + type = HIR::Literal::LitType::CHAR; + break; + case AST::Literal::LitType::STRING: + type = HIR::Literal::LitType::STRING; + break; + case AST::Literal::LitType::RAW_STRING: + type = HIR::Literal::LitType::RAW_STRING; + break; + case AST::Literal::LitType::BYTE: + type = HIR::Literal::LitType::BYTE; + break; + case AST::Literal::LitType::BYTE_STRING: + type = HIR::Literal::LitType::BYTE_STRING; + break; + case AST::Literal::LitType::RAW_BYTE_STRING: + type = HIR::Literal::LitType::RAW_BYTE_STRING; + break; + case AST::Literal::LitType::INT: + type = HIR::Literal::LitType::INT; + break; + case AST::Literal::LitType::FLOAT: + type = HIR::Literal::LitType::FLOAT; + break; + case AST::Literal::LitType::BOOL: + type = HIR::Literal::LitType::BOOL; + break; + } + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated = new HIR::LiteralExpr (mapping, expr.as_string (), type, + expr.get_locus ()); + } + + void visit (AST::ArithmeticOrLogicalExpr &expr) + { + HIR::ArithmeticOrLogicalExpr::ExprType kind + = HIR::ArithmeticOrLogicalExpr::ExprType::ADD; + switch (expr.get_expr_type ()) + { + case AST::ArithmeticOrLogicalExpr::ExprType::ADD: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::ADD; + break; + case AST::ArithmeticOrLogicalExpr::ExprType::SUBTRACT: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::SUBTRACT; + break; + case AST::ArithmeticOrLogicalExpr::ExprType::MULTIPLY: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::MULTIPLY; + break; + case AST::ArithmeticOrLogicalExpr::ExprType::DIVIDE: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::DIVIDE; + break; + case AST::ArithmeticOrLogicalExpr::ExprType::MODULUS: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::MODULUS; + break; + case AST::ArithmeticOrLogicalExpr::ExprType::BITWISE_AND: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_AND; + break; + case AST::ArithmeticOrLogicalExpr::ExprType::BITWISE_OR: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_OR; + break; + case AST::ArithmeticOrLogicalExpr::ExprType::BITWISE_XOR: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::BITWISE_XOR; + break; + case AST::ArithmeticOrLogicalExpr::ExprType::LEFT_SHIFT: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::LEFT_SHIFT; + break; + case AST::ArithmeticOrLogicalExpr::ExprType::RIGHT_SHIFT: + kind = HIR::ArithmeticOrLogicalExpr::ExprType::RIGHT_SHIFT; + break; + } + + HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ()); + rust_assert (lhs != nullptr); + HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ()); + rust_assert (rhs != nullptr); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, expr.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + translated + = new HIR::ArithmeticOrLogicalExpr (mapping, + std::unique_ptr<HIR::Expr> (lhs), + std::unique_ptr<HIR::Expr> (rhs), + kind, expr.get_locus ()); + } + +private: + ASTLoweringExpr () : translated (nullptr) {} + + HIR::Expr *translated; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_AST_LOWER_EXPR diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h new file mode 100644 index 0000000..e6c86b8 --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -0,0 +1,155 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_LOWER_ITEM +#define RUST_AST_LOWER_ITEM + +#include "rust-diagnostics.h" + +#include "rust-ast-lower-base.h" +#include "rust-ast-lower-type.h" +#include "rust-ast-lower-stmt.h" +#include "rust-ast-lower-pattern.h" + +namespace Rust { +namespace HIR { + +class ASTLoweringItem : public ASTLoweringBase +{ +public: + static HIR::Item *translate (AST::Item *item) + { + ASTLoweringItem resolver; + item->accept_vis (resolver); + return resolver.translated; + } + + virtual ~ASTLoweringItem () {} + + void visit (AST::Function &function) + { + // ignore for now and leave empty + std::vector<std::unique_ptr<HIR::GenericParam> > generic_params; + std::vector<HIR::Attribute> outer_attrs; + std::vector<std::unique_ptr<HIR::WhereClauseItem> > where_clause_items; + HIR::WhereClause where_clause (std::move (where_clause_items)); + HIR::FunctionQualifiers qualifiers ( + HIR::FunctionQualifiers::AsyncConstStatus::NONE, false); + HIR::Visibility vis = HIR::Visibility::create_public (); + + // need + Identifier function_name = function.get_function_name (); + Location locus = function.get_locus (); + + std::unique_ptr<HIR::Type> return_type + = function.has_return_type () ? std::unique_ptr<HIR::Type> ( + ASTLoweringType::translate (function.get_return_type ().get ())) + : nullptr; + + std::vector<HIR::FunctionParam> function_params; + for (auto ¶m : function.get_function_params ()) + { + auto translated_pattern = std::unique_ptr<HIR::Pattern> ( + ASTLoweringPattern::translate (param.get_pattern ().get ())); + auto translated_type = std::unique_ptr<HIR::Type> ( + ASTLoweringType::translate (param.get_type ().get ())); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, param.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + auto hir_param + = HIR::FunctionParam (mapping, std::move (translated_pattern), + std::move (translated_type), + param.get_locus ()); + function_params.push_back (hir_param); + } + + std::unique_ptr<HIR::BlockExpr> function_body + = std::unique_ptr<HIR::BlockExpr> ( + translate (function.get_definition ().get ())); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, function.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + + auto fn + = new HIR::Function (mapping, std::move (function_name), + std::move (qualifiers), std::move (generic_params), + std::move (function_params), std::move (return_type), + std::move (where_clause), std::move (function_body), + std::move (vis), std::move (outer_attrs), locus); + + mappings->insert_defid_mapping (mapping.get_defid (), translated); + mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), + fn); + mappings->insert_location (crate_num, mapping.get_hirid (), + function.get_locus ()); + + // add the mappings for the function params at the end + for (auto ¶m : fn->function_params) + { + mappings->insert_hir_param (mapping.get_crate_num (), + param.get_mappings ()->get_hirid (), + ¶m); + mappings->insert_location (crate_num, mapping.get_hirid (), + param.get_locus ()); + } + + translated = fn; + } + + // Helpers + + HIR::BlockExpr *translate (AST::BlockExpr *function_body) + { + std::vector<std::unique_ptr<HIR::Stmt> > block_stmts; + std::unique_ptr<HIR::ExprWithoutBlock> block_expr; + std::vector<HIR::Attribute> inner_attribs; + std::vector<HIR::Attribute> outer_attribs; + + function_body->iterate_stmts ([&] (AST::Stmt *s) mutable -> bool { + auto translated_stmt = ASTLoweringStmt::translate (s); + block_stmts.push_back (std::unique_ptr<HIR::Stmt> (translated_stmt)); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, function_body->get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + return new HIR::BlockExpr (mapping, std::move (block_stmts), + std::move (block_expr), + std::move (inner_attribs), + std::move (outer_attribs), + function_body->get_locus ()); + } + +private: + ASTLoweringItem () : translated (nullptr) {} + + HIR::Item *translated; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_AST_LOWER_ITEM diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h b/gcc/rust/hir/rust-ast-lower-pattern.h new file mode 100644 index 0000000..0d5ce0f --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-pattern.h @@ -0,0 +1,58 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_LOWER_PATTERN +#define RUST_AST_LOWER_PATTERN + +#include "rust-ast-lower-base.h" +#include "rust-diagnostics.h" + +namespace Rust { +namespace HIR { + +class ASTLoweringPattern : public ASTLoweringBase +{ +public: + static HIR::Pattern *translate (AST::Pattern *pattern) + { + ASTLoweringPattern resolver; + pattern->accept_vis (resolver); + return resolver.translated; + } + + virtual ~ASTLoweringPattern () {} + + void visit (AST::IdentifierPattern &pattern) + { + std::unique_ptr<Pattern> to_bind; + translated + = new HIR::IdentifierPattern (pattern.get_ident (), pattern.get_locus (), + pattern.get_is_ref (), + pattern.get_is_mut (), std::move (to_bind)); + } + +private: + ASTLoweringPattern () : translated (nullptr) {} + + HIR::Pattern *translated; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_AST_LOWER_PATTERN diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h new file mode 100644 index 0000000..c57d14f --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -0,0 +1,102 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_LOWER_STMT +#define RUST_AST_LOWER_STMT + +#include "rust-diagnostics.h" + +#include "rust-ast-lower-base.h" +#include "rust-ast-lower-type.h" +#include "rust-ast-lower-expr.h" +#include "rust-ast-lower-pattern.h" + +namespace Rust { +namespace HIR { + +class ASTLoweringStmt : public ASTLoweringBase +{ +public: + static HIR::Stmt *translate (AST::Stmt *stmt) + { + ASTLoweringStmt resolver; + stmt->accept_vis (resolver); + if (resolver.translated == nullptr) + { + printf ("Failing translating: %s\n", stmt->as_string ().c_str ()); + rust_assert (resolver.translated != nullptr); + } + return resolver.translated; + } + + virtual ~ASTLoweringStmt () {} + + void visit (AST::ExprStmtWithoutBlock &stmt) + { + HIR::Expr *expr = ASTLoweringExpr::translate (stmt.get_expr ().get ()); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + translated + = new HIR::ExprStmtWithoutBlock (mapping, + std::unique_ptr<HIR::Expr> (expr), + stmt.get_locus ()); + mappings->insert_location (crate_num, mapping.get_hirid (), + stmt.get_locus ()); + mappings->insert_hir_stmt (crate_num, mapping.get_hirid (), translated); + } + + void visit (AST::LetStmt &stmt) + { + std::vector<HIR::Attribute> outer_attrs; + HIR::Pattern *variables + = ASTLoweringPattern::translate (stmt.get_pattern ().get ()); + HIR::Type *type = stmt.has_type () + ? ASTLoweringType::translate (stmt.get_type ().get ()) + : nullptr; + HIR::Expr *init_expression + = stmt.has_init_expr () + ? ASTLoweringExpr::translate (stmt.get_init_expr ().get ()) + : nullptr; + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, stmt.get_node_id (), + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + translated + = new HIR::LetStmt (mapping, std::unique_ptr<HIR::Pattern> (variables), + std::unique_ptr<HIR::Expr> (init_expression), + std::unique_ptr<HIR::Type> (type), + std::move (outer_attrs), stmt.get_locus ()); + mappings->insert_location (crate_num, mapping.get_hirid (), + stmt.get_locus ()); + mappings->insert_hir_stmt (crate_num, mapping.get_hirid (), translated); + } + +private: + ASTLoweringStmt () : translated (nullptr) {} + + HIR::Stmt *translated; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_AST_LOWER_PATTERN diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h new file mode 100644 index 0000000..4193415 --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -0,0 +1,91 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_LOWER_TYPE +#define RUST_AST_LOWER_TYPE + +#include "rust-ast-lower-base.h" +#include "rust-diagnostics.h" + +namespace Rust { +namespace HIR { + +class ASTLoweringType : public ASTLoweringBase +{ +public: + static HIR::Type *translate (AST::Type *type) + { + ASTLoweringType resolver; + type->accept_vis (resolver); + return resolver.translated; + } + + virtual ~ASTLoweringType () {} + + virtual void visit (AST::TypePathSegment &segment) + { + HIR::PathIdentSegment ident (segment.get_ident_segment ().as_string ()); + translated_segment + = new HIR::TypePathSegment (ident, + segment.get_separating_scope_resolution (), + segment.get_locus ()); + } + + virtual void visit (AST::TypePath &path) + { + std::vector<std::unique_ptr<HIR::TypePathSegment> > translated_segments; + + path.iterate_segments ([&] (AST::TypePathSegment *seg) mutable -> bool { + translated_segment = nullptr; + seg->accept_vis (*this); + if (translated_segment == nullptr) + { + rust_fatal_error (seg->get_locus (), + "failed to translate AST TypePathSegment"); + return false; + } + + translated_segments.push_back ( + std::unique_ptr<HIR::TypePathSegment> (translated_segment)); + return true; + }); + + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, path.get_node_id (), + mappings->get_next_hir_id (crate_num), + mappings->get_next_localdef_id (crate_num)); + translated + = new HIR::TypePath (std::move (mapping), std::move (translated_segments), + path.get_locus (), + path.has_opening_scope_resolution_op ()); + mappings->insert_hir_type (mapping.get_crate_num (), mapping.get_hirid (), + translated); + } + +private: + ASTLoweringType () : translated (nullptr) {} + + HIR::Type *translated; + + HIR::TypePathSegment *translated_segment; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_AST_LOWER_TYPE diff --git a/gcc/rust/hir/rust-ast-lower.cc b/gcc/rust/hir/rust-ast-lower.cc new file mode 100644 index 0000000..8a514ce --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower.cc @@ -0,0 +1,62 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-ast-lower.h" +#include "rust-ast-lower-item.h" + +namespace Rust { +namespace HIR { + +ASTLowering::ASTLowering (AST::Crate &astCrate) : astCrate (astCrate) {} + +ASTLowering::~ASTLowering () {} + +HIR::Crate +ASTLowering::Resolve (AST::Crate &astCrate) +{ + ASTLowering resolver (astCrate); + return resolver.go (); +} + +HIR::Crate +ASTLowering::go () +{ + std::vector<std::unique_ptr<HIR::Item> > items; + std::vector<HIR::Attribute> inner_attrs; + bool has_utf8bom = false; + bool has_shebang = false; + + for (auto it = astCrate.items.begin (); it != astCrate.items.end (); it++) + { + auto translated = ASTLoweringItem::translate (it->get ()); + if (translated != nullptr) + items.push_back (std::unique_ptr<HIR::Item> (translated)); + } + + auto mappings = Analysis::Mappings::get (); + auto crate_num = mappings->get_current_crate (); + Analysis::NodeMapping mapping (crate_num, UNKNOWN_NODEID, + mappings->get_next_hir_id (crate_num), + UNKNOWN_LOCAL_DEFID); + + return HIR::Crate (std::move (items), std::move (inner_attrs), mapping, + has_utf8bom, has_shebang); +} + +} // namespace HIR +} // namespace Rust diff --git a/gcc/rust/hir/rust-ast-lower.h b/gcc/rust/hir/rust-ast-lower.h new file mode 100644 index 0000000..bdc21ba --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower.h @@ -0,0 +1,46 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_LOWER +#define RUST_HIR_LOWER + +#include "rust-system.h" +#include "rust-ast-full.h" +#include "rust-ast-visitor.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace HIR { + +class ASTLowering +{ +public: + static HIR::Crate Resolve (AST::Crate &astCrate); + ~ASTLowering (); + +private: + ASTLowering (AST::Crate &astCrate); + HIR::Crate go (); + + AST::Crate &astCrate; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_HIR_LOWER diff --git a/gcc/rust/hir/tree/rust-hir-cond-compilation.h b/gcc/rust/hir/tree/rust-hir-cond-compilation.h new file mode 100644 index 0000000..3a1ddf2 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-cond-compilation.h @@ -0,0 +1,248 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_CONDCOMPILATION +#define RUST_AST_CONDCOMPILATION + +#include "rust-hir.h" + +namespace Rust { +namespace HIR { +// 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 (HIRVisitor &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. */ + 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) {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 ()) + {} + + // 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) + {} + + // 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 HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h new file mode 100644 index 0000000..36c2085 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -0,0 +1,4504 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_EXPR_H +#define RUST_HIR_EXPR_H + +#include "rust-hir.h" +#include "rust-hir-path.h" + +namespace Rust { +namespace HIR { + +// HIR 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 (Analysis::NodeMapping mappings, + std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) + : Expr (std::move (mappings), std::move (outer_attrs)) + {} + + // pure virtual clone implementation + virtual ExprWithBlock *clone_expr_with_block_impl () const = 0; + + // prevent having to define multiple clone expressions + ExprWithBlock *clone_expr_impl () const override + { + return clone_expr_with_block_impl (); + } + + bool is_expr_without_block () const final override { return false; }; + +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 +{ + Literal literal; + Location locus; + +public: + std::string as_string () const override { return literal.as_string (); } + + Literal::LitType get_lit_type () const { return literal.get_lit_type (); } + + LiteralExpr (Analysis::NodeMapping mappings, std::string value_as_string, + Literal::LitType type, Location locus, + std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), + literal (std::move (value_as_string), type), locus (locus) + {} + + LiteralExpr (Analysis::NodeMapping mappings, Literal literal, Location locus, + std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) + : ExprWithoutBlock (std::move (mappings), 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 (); } + + void accept_vis (HIRVisitor &vis) override; + + Literal *get_literal () { return &literal; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + LiteralExpr *clone_expr_impl () const override + { + return new LiteralExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 + // 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)) + {} + + std::string as_string () const override + { + return " = " + literal_expr.as_string (); + } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Use covariance to implement clone function as returning this type + 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 (); + } + + void accept_vis (HIRVisitor &vis) override; + + Attribute to_attribute () const override; + +protected: + // Use covariance to implement clone function as returning this type + MetaItemPathLit *clone_meta_item_inner_impl () const override + { + return new MetaItemPathLit (*this); + } +}; + +/* Represents an expression using unary or binary operators as HIR node. Can be + * overloaded. */ +class OperatorExpr : public ExprWithoutBlock +{ + // TODO: create binary and unary operator subclasses? +public: + Location locus; + +protected: + /* Variable must be protected to allow derived classes to use it as a first + * class citizen */ + std::unique_ptr<Expr> main_or_left_expr; + + // Constructor (only for initialisation of expr purposes) + OperatorExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> main_or_left_expr, + std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), 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 ()) + {} + + // 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: + 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 override; + + BorrowExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> borrow_lvalue, bool is_mut_borrow, + bool is_double_borrow, std::vector<Attribute> outer_attribs, + Location locus) + : OperatorExpr (std::move (mappings), std::move (borrow_lvalue), + std::move (outer_attribs), locus), + is_mut (is_mut_borrow), double_borrow (is_double_borrow) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + BorrowExpr *clone_expr_impl () const override + { + return new BorrowExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + BorrowExpr *clone_expr_without_block_impl () const override + { + return new BorrowExpr (*this); + } +}; + +// Unary prefix * deference operator +class DereferenceExpr : public OperatorExpr +{ +public: + std::string as_string () const override; + + // Constructor calls OperatorExpr's protected constructor + DereferenceExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> deref_lvalue, + std::vector<Attribute> outer_attribs, Location locus) + : OperatorExpr (std::move (mappings), std::move (deref_lvalue), + std::move (outer_attribs), locus) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + DereferenceExpr *clone_expr_impl () const override + { + return new DereferenceExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + DereferenceExpr *clone_expr_without_block_impl () const override + { + return new DereferenceExpr (*this); + } +}; + +// Unary postfix ? error propogation operator. Cannot be overloaded. +class ErrorPropagationExpr : public OperatorExpr +{ +public: + std::string as_string () const override; + + // Constructor calls OperatorExpr's protected constructor + ErrorPropagationExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> potential_error_value, + std::vector<Attribute> outer_attribs, Location locus) + : OperatorExpr (std::move (mappings), std::move (potential_error_value), + std::move (outer_attribs), locus) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ErrorPropagationExpr *clone_expr_impl () const override + { + return new ErrorPropagationExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ErrorPropagationExpr *clone_expr_without_block_impl () const override + { + return new ErrorPropagationExpr (*this); + } +}; + +// Unary prefix - or ! negation or NOT operators. +class NegationExpr : public OperatorExpr +{ +public: + enum NegationType + { + NEGATE, + NOT + }; + + /* 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 override; + + NegationType get_negation_type () const { return negation_type; } + + // Constructor calls OperatorExpr's protected constructor + NegationExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> negated_value, NegationType negation_kind, + std::vector<Attribute> outer_attribs, Location locus) + : OperatorExpr (std::move (mappings), std::move (negated_value), + std::move (outer_attribs), locus), + negation_type (negation_kind) + {} + + void accept_vis (HIRVisitor &vis) override; + + Expr *get_expr () { return main_or_left_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + NegationExpr *clone_expr_impl () const override + { + return new NegationExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + NegationExpr *clone_expr_without_block_impl () const override + { + 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 + }; + + // Note: overloading trait specified in comments + ExprType expr_type; + + std::unique_ptr<Expr> right_expr; + +public: + std::string as_string () const override; + + ExprType get_expr_type () const { return expr_type; } + + // Constructor calls OperatorExpr's protected constructor + ArithmeticOrLogicalExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> left_value, + std::unique_ptr<Expr> right_value, + ExprType expr_kind, Location locus) + : OperatorExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + + void visit_lhs (HIRVisitor &vis) { main_or_left_expr->accept_vis (vis); } + void visit_rhs (HIRVisitor &vis) { right_expr->accept_vis (vis); } + + Expr *get_lhs () { return main_or_left_expr.get (); } + Expr *get_rhs () { return right_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArithmeticOrLogicalExpr *clone_expr_impl () const override + { + return new ArithmeticOrLogicalExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArithmeticOrLogicalExpr *clone_expr_without_block_impl () const override + { + 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 + }; + + // Note: overloading trait specified in comments + ExprType expr_type; + + std::unique_ptr<Expr> right_expr; + +public: + std::string as_string () const override; + + ExprType get_expr_type () const { return expr_type; } + + // Constructor requires pointers for polymorphism + ComparisonExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> left_value, + std::unique_ptr<Expr> right_value, ExprType comparison_kind, + Location locus) + : OperatorExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + + Expr *get_lhs () { return main_or_left_expr.get (); } + Expr *get_rhs () { return right_expr.get (); } + + /* 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 */ + ComparisonExpr *clone_expr_impl () const override + { + return new ComparisonExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ComparisonExpr *clone_expr_without_block_impl () const override + { + return new ComparisonExpr (*this); + } +}; + +// Infix binary lazy boolean logical operators && and ||. +class LazyBooleanExpr : public OperatorExpr +{ +public: + enum ExprType + { + LOGICAL_OR, + LOGICAL_AND + }; + + ExprType expr_type; + + std::unique_ptr<Expr> right_expr; + +public: + // Constructor calls OperatorExpr's protected constructor + LazyBooleanExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> left_bool_expr, + std::unique_ptr<Expr> right_bool_expr, ExprType expr_kind, + Location locus) + : OperatorExpr (std::move (mappings), 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 ()) + {} + + // 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 override; + + ExprType get_expr_type () const { return expr_type; } + + void accept_vis (HIRVisitor &vis) override; + + Expr *get_lhs () { return main_or_left_expr.get (); } + + Expr *get_rhs () { return right_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + LazyBooleanExpr *clone_expr_impl () const override + { + return new LazyBooleanExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + LazyBooleanExpr *clone_expr_without_block_impl () const override + { + return new LazyBooleanExpr (*this); + } +}; + +// Binary infix "as" chir expression. +class TypeCastExpr : public OperatorExpr +{ + std::unique_ptr<TypeNoBounds> type_to_convert_to; + + // Note: only certain type casts allowed, outlined in reference +public: + std::string as_string () const override; + + // Constructor requires calling protected constructor of OperatorExpr + TypeCastExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> expr_to_cast, + std::unique_ptr<TypeNoBounds> type_to_cast_to, Location locus) + : OperatorExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TypeCastExpr *clone_expr_impl () const override + { + return new TypeCastExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + TypeCastExpr *clone_expr_without_block_impl () const override + { + return new TypeCastExpr (*this); + } +}; + +// Binary assignment expression. +class AssignmentExpr : public OperatorExpr +{ + std::unique_ptr<Expr> right_expr; + +public: + std::string as_string () const override; + + // Call OperatorExpr constructor to initialise left_expr + AssignmentExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> value_to_assign_to, + std::unique_ptr<Expr> value_to_assign, Location locus) + : OperatorExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + + void visit_lhs (HIRVisitor &vis) { main_or_left_expr->accept_vis (vis); } + void visit_rhs (HIRVisitor &vis) { right_expr->accept_vis (vis); } + + Expr *get_lhs () { return main_or_left_expr.get (); } + Expr *get_rhs () { return right_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + AssignmentExpr *clone_expr_impl () const override + { + return new AssignmentExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + AssignmentExpr *clone_expr_without_block_impl () const override + { + 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; + std::unique_ptr<Expr> right_expr; + +public: + std::string as_string () const override; + + ExprType get_expr_type () const { return expr_type; } + + // Use pointers in constructor to enable polymorphism + CompoundAssignmentExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> value_to_assign_to, + std::unique_ptr<Expr> value_to_assign, + ExprType expr_kind, Location locus) + : OperatorExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + CompoundAssignmentExpr *clone_expr_impl () const override + { + return new CompoundAssignmentExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + CompoundAssignmentExpr *clone_expr_without_block_impl () const override + { + 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; + std::unique_ptr<Expr> expr_in_parens; + + Location locus; + +public: + std::string as_string () const override; + + std::vector<Attribute> get_inner_attrs () const { return inner_attrs; } + + GroupedExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> parenthesised_expr, + std::vector<Attribute> inner_attribs, + std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), 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) + {} + + // 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + GroupedExpr *clone_expr_impl () const override + { + return new GroupedExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 (HIRVisitor &vis) = 0; + +protected: + // pure virtual clone implementation + virtual ArrayElems *clone_array_elems_impl () const = 0; +}; + +// Value array elements +class ArrayElemsValues : public ArrayElems +{ + std::vector<std::unique_ptr<Expr> > values; + + // TODO: should this store location data? + +public: + ArrayElemsValues (std::vector<std::unique_ptr<Expr> > elems) + : values (std::move (elems)) + {} + + // copy constructor with vector clone + ArrayElemsValues (ArrayElemsValues const &other) + { + 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) + { + 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 override; + + void accept_vis (HIRVisitor &vis) override; + + size_t get_num_values () const { return values.size (); } + + void iterate (std::function<bool (Expr *)> cb) + { + for (auto it = values.begin (); it != values.end (); it++) + { + if (!cb ((*it).get ())) + return; + } + } + +protected: + ArrayElemsValues *clone_array_elems_impl () const override + { + return new ArrayElemsValues (*this); + } +}; + +// Copied array element and number of copies +class ArrayElemsCopied : public ArrayElems +{ + std::unique_ptr<Expr> elem_to_copy; + std::unique_ptr<Expr> num_copies; + + // TODO: should this store location data? + +public: + // 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 ()) + {} + + // 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + ArrayElemsCopied *clone_array_elems_impl () const override + { + return new ArrayElemsCopied (*this); + } +}; + +// Array definition-ish expression +class ArrayExpr : public ExprWithoutBlock +{ + std::vector<Attribute> inner_attrs; + std::unique_ptr<ArrayElems> internal_elements; + + Location locus; + + // this is a reference to what the inferred type is based on + // this init expression + Type *inferredType; + +public: + std::string as_string () const override; + + std::vector<Attribute> get_inner_attrs () const { return inner_attrs; } + + // Returns whether array expr has array elems or if it is just empty. + bool has_array_elems () const { return internal_elements != nullptr; } + + // Constructor requires ArrayElems pointer + ArrayExpr (Analysis::NodeMapping mappings, + std::unique_ptr<ArrayElems> array_elems, + std::vector<Attribute> inner_attribs, + std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), 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 (); + } + + // 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 (); } + + void accept_vis (HIRVisitor &vis) override; + + ArrayElems *get_internal_elements () { return internal_elements.get (); }; + + Type *get_inferred_type () { return inferredType; } + void set_inferred_type (Type *type) { inferredType = type; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayExpr *clone_expr_impl () const override { return new ArrayExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 +{ + std::unique_ptr<Expr> array_expr; + std::unique_ptr<Expr> index_expr; + + Location locus; + +public: + std::string as_string () const override; + + ArrayIndexExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> array_expr, + std::unique_ptr<Expr> array_index_expr, + std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), 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) + {} + + // 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 (); } + + void accept_vis (HIRVisitor &vis) override; + + Expr *get_array_expr () { return array_expr.get (); } + Expr *get_index_expr () { return index_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayIndexExpr *clone_expr_impl () const override + { + return new ArrayIndexExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayIndexExpr *clone_expr_without_block_impl () const override + { + return new ArrayIndexExpr (*this); + } +}; + +// HIR representation of a tuple +class TupleExpr : public ExprWithoutBlock +{ + std::vector<Attribute> inner_attrs; + + std::vector<std::unique_ptr<Expr> > tuple_elems; + // replaces (inlined version of) TupleElements + + Location locus; + +public: + std::string as_string () const override; + + std::vector<Attribute> get_inner_attrs () const { return inner_attrs; } + + TupleExpr (Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<Expr> > tuple_elements, + std::vector<Attribute> inner_attribs, + std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), 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) + { + 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; + + 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleExpr *clone_expr_impl () const override { return new TupleExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleExpr *clone_expr_without_block_impl () const override + { + return new TupleExpr (*this); + } +}; + +// aka TupleIndexingExpr +// HIR representation of a tuple indexing expression +class TupleIndexExpr : public ExprWithoutBlock +{ + 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: + std::string as_string () const override; + + TupleIndex get_tuple_index () const { return tuple_index; } + + TupleIndexExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> tuple_expr, TupleIndex index, + std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), 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) + {} + + // 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleIndexExpr *clone_expr_impl () const override + { + return new TupleIndexExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleIndexExpr *clone_expr_without_block_impl () const override + { + return new TupleIndexExpr (*this); + } +}; + +// Base struct/tuple/union value creator HIR node (abstract) +class StructExpr : public ExprWithoutBlock +{ + PathInExpression struct_name; + +protected: + // Protected constructor to allow initialising struct_name + StructExpr (Analysis::NodeMapping mappings, PathInExpression struct_path, + std::vector<Attribute> outer_attribs) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + struct_name (std::move (struct_path)) + {} + +public: + const PathInExpression &get_struct_name () const { return struct_name; } + + std::string as_string () const override; +}; + +// Actual HIR 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 override; + + std::vector<Attribute> get_inner_attrs () const { return inner_attrs; } + + // Constructor has to call protected constructor of base class + StructExprStruct (Analysis::NodeMapping mappings, + PathInExpression struct_path, + std::vector<Attribute> inner_attribs, + std::vector<Attribute> outer_attribs, Location locus) + : StructExpr (std::move (mappings), 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStruct *clone_expr_impl () const override + { + return new StructExprStruct (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStruct *clone_expr_without_block_impl () const override + { + return new StructExprStruct (*this); + } +}; + +/* HIR node representing expression used to fill a struct's fields from another + * struct */ +struct StructBase +{ +public: + std::unique_ptr<Expr> base_struct; + + // TODO: should this store location data? + 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 != nullptr) + other.base_struct->clone_expr (); + } + + // 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; + + // Returns a null expr-ed StructBase - error state + static StructBase error () { return StructBase (nullptr); } + + // Returns whether StructBase is in error state + bool is_invalid () const { return base_struct == nullptr; } + + std::string as_string () const; +}; + +/* Base HIR 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 (HIRVisitor &vis) = 0; + +protected: + // pure virtual clone implementation + virtual StructExprField *clone_struct_expr_field_impl () const = 0; +}; + +// Identifier-only variant of StructExprField HIR node +class StructExprFieldIdentifier : public StructExprField +{ +public: + Identifier field_name; + + // TODO: should this store location data? + + StructExprFieldIdentifier (Identifier field_identifier) + : field_name (std::move (field_identifier)) + {} + + std::string as_string () const override { return field_name; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprFieldIdentifier *clone_struct_expr_field_impl () const override + { + return new StructExprFieldIdentifier (*this); + } +}; + +/* Base HIR node for a single struct expression field with an assigned value - + * abstract */ +class StructExprFieldWithVal : public StructExprField +{ +public: + 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 ()) + {} + + // 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: + std::string as_string () const override; +}; + +// Identifier and value variant of StructExprField HIR node +class StructExprFieldIdentifierValue : public StructExprFieldWithVal +{ +public: + Identifier field_name; + + // TODO: should this store location data? + + StructExprFieldIdentifierValue (Identifier field_identifier, + std::unique_ptr<Expr> field_value) + : StructExprFieldWithVal (std::move (field_value)), + field_name (std::move (field_identifier)) + {} + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprFieldIdentifierValue *clone_struct_expr_field_impl () const override + { + return new StructExprFieldIdentifierValue (*this); + } +}; + +// Tuple index and value variant of StructExprField HIR node +class StructExprFieldIndexValue : public StructExprFieldWithVal +{ +public: + TupleIndex index; + + // TODO: should this store location data? + + StructExprFieldIndexValue (TupleIndex tuple_index, + std::unique_ptr<Expr> field_value) + : StructExprFieldWithVal (std::move (field_value)), index (tuple_index) + {} + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprFieldIndexValue *clone_struct_expr_field_impl () const override + { + return new StructExprFieldIndexValue (*this); + } +}; + +// HIR node of a struct creator with fields +class StructExprStructFields : public StructExprStruct +{ +public: + // std::vector<StructExprField> fields; + std::vector<std::unique_ptr<StructExprField> > fields; + + // bool has_struct_base; + StructBase struct_base; + + std::string as_string () const override; + + 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 ( + Analysis::NodeMapping mappings, 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 (mappings), 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) + { + fields.reserve (other.fields.size ()); + for (const auto &e : other.fields) + fields.push_back (e->clone_struct_expr_field ()); + } + + // overloaded assignment operator with vector clone + StructExprStructFields &operator= (StructExprStructFields const &other) + { + StructExprStruct::operator= (other); + struct_base = other.struct_base; + + 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStructFields *clone_expr_impl () const override + { + return new StructExprStructFields (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStructFields *clone_expr_without_block_impl () const override + { + return new StructExprStructFields (*this); + } +}; + +// HIR node of the functional update struct creator +class StructExprStructBase : public StructExprStruct +{ + StructBase struct_base; + +public: + std::string as_string () const override; + + /*inline StructBase get_struct_base() const { + return struct_base; + }*/ + + StructExprStructBase (Analysis::NodeMapping mappings, + PathInExpression struct_path, StructBase base_struct, + std::vector<Attribute> inner_attribs, + std::vector<Attribute> outer_attribs, Location locus) + : StructExprStruct (std::move (mappings), std::move (struct_path), + std::move (inner_attribs), std::move (outer_attribs), + locus), + struct_base (std::move (base_struct)) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStructBase *clone_expr_impl () const override + { + return new StructExprStructBase (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprStructBase *clone_expr_without_block_impl () const override + { + return new StructExprStructBase (*this); + } +}; + +// HIR node of a tuple struct creator +class StructExprTuple : public StructExpr +{ + std::vector<Attribute> inner_attrs; + std::vector<std::unique_ptr<Expr> > exprs; + + Location locus; + +public: + std::string as_string () const override; + + const std::vector<Attribute> &get_inner_attrs () const { return inner_attrs; } + + /*inline std::vector<std::unique_ptr<Expr>> get_exprs() const { + return exprs; + }*/ + + StructExprTuple (Analysis::NodeMapping mappings, 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 (mappings), 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) + { + 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; + + 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprTuple *clone_expr_impl () const override + { + return new StructExprTuple (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprTuple *clone_expr_without_block_impl () const override + { + return new StructExprTuple (*this); + } +}; + +// HIR node of a "unit" struct creator (no fields and no braces) +class StructExprUnit : public StructExpr +{ + Location locus; + +public: + std::string as_string () const override + { + return get_struct_name ().as_string (); + // return struct_name.as_string(); + } + + StructExprUnit (Analysis::NodeMapping mappings, PathInExpression struct_path, + std::vector<Attribute> outer_attribs, Location locus) + : StructExpr (std::move (mappings), 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprUnit *clone_expr_impl () const override + { + return new StructExprUnit (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + StructExprUnit *clone_expr_without_block_impl () const override + { + return new StructExprUnit (*this); + } +}; + +// aka EnumerationVariantExpr +// Base HIR 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 (Analysis::NodeMapping mappings, + PathInExpression path_to_enum_variant, + std::vector<Attribute> outer_attribs) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + enum_variant_path (std::move (path_to_enum_variant)) + {} + +public: + // TODO: maybe remove and have string version gotten here directly + PathInExpression get_enum_variant_path () const { return enum_variant_path; } +}; + +/* Base HIR 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 (HIRVisitor &vis) = 0; + +protected: + // Clone function implementation as pure virtual method + virtual EnumExprField *clone_enum_expr_field_impl () const = 0; +}; + +// Identifier-only variant of EnumExprField HIR 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)) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + EnumExprFieldIdentifier *clone_enum_expr_field_impl () const override + { + return new EnumExprFieldIdentifier (*this); + } +}; + +/* Base HIR node for a single enum expression field with an assigned value - + * abstract */ +class EnumExprFieldWithVal : public EnumExprField +{ + 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 ()) + {} + + // 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 HIR 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 + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + EnumExprFieldIdentifierValue *clone_enum_expr_field_impl () const override + { + return new EnumExprFieldIdentifierValue (*this); + } +}; + +// Tuple index and value variant of EnumExprField HIR 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) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + EnumExprFieldIndexValue *clone_enum_expr_field_impl () const override + { + return new EnumExprFieldIndexValue (*this); + } +}; + +// Struct-like syntax enum variant instance creation HIR node +class EnumExprStruct : public EnumVariantExpr +{ + // std::vector<EnumExprField> fields; + std::vector<std::unique_ptr<EnumExprField> > fields; + + Location locus; + +public: + std::string as_string () const override; + + /*inline std::vector<std::unique_ptr<EnumExprField>> get_fields() const + { return fields; + }*/ + + EnumExprStruct (Analysis::NodeMapping mappings, + PathInExpression enum_variant_path, + std::vector<std::unique_ptr<EnumExprField> > variant_fields, + std::vector<Attribute> outer_attribs, Location locus) + : EnumVariantExpr (std::move (mappings), 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) + { + 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; + + 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + EnumExprStruct *clone_expr_impl () const override + { + return new EnumExprStruct (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + EnumExprStruct *clone_expr_without_block_impl () const override + { + return new EnumExprStruct (*this); + } +}; + +// Tuple-like syntax enum variant instance creation HIR node +class EnumExprTuple : public EnumVariantExpr +{ + std::vector<std::unique_ptr<Expr> > values; + + Location locus; + +public: + std::string as_string () const override; + + /*inline std::vector<std::unique_ptr<Expr>> get_values() const { + return values; + }*/ + + EnumExprTuple (Analysis::NodeMapping mappings, + PathInExpression enum_variant_path, + std::vector<std::unique_ptr<Expr> > variant_values, + std::vector<Attribute> outer_attribs, Location locus) + : EnumVariantExpr (std::move (mappings), 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) + { + 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; + + 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + EnumExprTuple *clone_expr_impl () const override + { + return new EnumExprTuple (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + EnumExprTuple *clone_expr_without_block_impl () const override + { + return new EnumExprTuple (*this); + } +}; + +// No-field enum variant instance creation HIR node +class EnumExprFieldless : public EnumVariantExpr +{ + Location locus; + +public: + std::string as_string () const override + { + // return enum_variant_path.as_string(); + return get_enum_variant_path ().as_string (); + } + + EnumExprFieldless (Analysis::NodeMapping mappings, + PathInExpression enum_variant_path, + std::vector<Attribute> outer_attribs, Location locus) + : EnumVariantExpr (std::move (mappings), std::move (enum_variant_path), + std::move (outer_attribs)), + locus (locus) + {} + + Location get_locus () const { return locus; } + Location get_locus_slow () const override { return get_locus (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + EnumExprFieldless *clone_expr_impl () const override + { + return new EnumExprFieldless (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + EnumExprFieldless *clone_expr_without_block_impl () const override + { + return new EnumExprFieldless (*this); + } +}; + +// Forward decl for Function - used in CallExpr +class Function; + +// Function call expression HIR node +class CallExpr : public ExprWithoutBlock +{ + std::unique_ptr<Expr> function; + // inlined form of CallParams + std::vector<std::unique_ptr<Expr> > params; + + Location locus; + +public: + std::string as_string () const override; + + CallExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> function_expr, + std::vector<std::unique_ptr<Expr> > function_params, + std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), 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),*/ { + params.reserve (other.params.size ()); + for (const auto &e : other.params) + params.push_back (e->clone_expr ()); + } + + // 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; + + 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. + bool has_params () const { return !params.empty (); } + + Location get_locus () const { return locus; } + Location get_locus_slow () const override { return get_locus (); } + + void accept_vis (HIRVisitor &vis) override; + + Expr *get_fnexpr () { return function.get (); } + + size_t num_params () const { return params.size (); } + + void iterate_params (std::function<bool (Expr *)> cb) + { + for (auto it = params.begin (); it != params.end (); it++) + { + if (!cb (it->get ())) + return; + } + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + CallExpr *clone_expr_impl () const override { return new CallExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + CallExpr *clone_expr_without_block_impl () const override + { + return new CallExpr (*this); + } +}; + +// Method call expression HIR node +class MethodCallExpr : public ExprWithoutBlock +{ + std::unique_ptr<Expr> receiver; + PathExprSegment method_name; + // inlined form of CallParams + std::vector<std::unique_ptr<Expr> > params; + + Location locus; + +public: + std::string as_string () const override; + + /*inline std::vector<std::unique_ptr<Expr>> get_params() const { + return params; + }*/ + + MethodCallExpr (Analysis::NodeMapping mappings, + 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 (mappings), 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),*/ { + params.reserve (other.params.size ()); + for (const auto &e : other.params) + params.push_back (e->clone_expr ()); + } + + // 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; + + 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + MethodCallExpr *clone_expr_impl () const override + { + return new MethodCallExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MethodCallExpr *clone_expr_without_block_impl () const override + { + return new MethodCallExpr (*this); + } +}; + +// aka FieldExpression +// Struct or union field access expression HIR node +class FieldAccessExpr : public ExprWithoutBlock +{ + std::unique_ptr<Expr> receiver; + Identifier field; + + Location locus; + +public: + std::string as_string () const override; + + FieldAccessExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> field_access_receiver, + Identifier field_name, std::vector<Attribute> outer_attribs, + Location locus) + : ExprWithoutBlock (std::move (mappings), 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) + {} + + // 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + FieldAccessExpr *clone_expr_impl () const override + { + return new FieldAccessExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + FieldAccessExpr *clone_expr_without_block_impl () const override + { + return new FieldAccessExpr (*this); + } +}; + +// Closure parameter data structure +struct ClosureParam +{ +private: + std::unique_ptr<Pattern> pattern; + + // bool has_type_given; + std::unique_ptr<Type> type; + + // TODO: should this store location data? + +public: + // Returns whether the type of the parameter has been given. + bool has_type_given () const { return type != nullptr; } + + // Constructor for closure parameter + ClosureParam (std::unique_ptr<Pattern> param_pattern, + std::unique_ptr<Type> param_type = nullptr) + : 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 != nullptr) + 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. + bool is_error () const { return pattern == nullptr; } + + // Creates an error state closure parameter. + static ClosureParam create_error () { return ClosureParam (nullptr); } + + std::string as_string () const; +}; + +// Base closure definition expression HIR 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 (Analysis::NodeMapping mappings, + std::vector<ClosureParam> closure_params, bool has_move, + std::vector<Attribute> outer_attribs, Location locus) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + has_move (has_move), params (std::move (closure_params)), locus (locus) + {} + +public: + std::string as_string () const override; + + Location get_locus () const { return locus; } + Location get_locus_slow () const override { return get_locus (); } +}; + +// Represents a non-type-specified closure expression HIR node +class ClosureExprInner : public ClosureExpr +{ + std::unique_ptr<Expr> closure_inner; + +public: + std::string as_string () const override; + + // Constructor for a ClosureExprInner + ClosureExprInner (Analysis::NodeMapping mappings, + 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 (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ClosureExprInner *clone_expr_impl () const override + { + return new ClosureExprInner (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ClosureExprInner *clone_expr_without_block_impl () const override + { + return new ClosureExprInner (*this); + } +}; + +// A block HIR node +class BlockExpr : public ExprWithBlock +{ +public: + std::vector<Attribute> inner_attrs; + + // bool has_statements; + std::vector<std::unique_ptr<Stmt> > statements; + // bool has_expr; + std::unique_ptr<ExprWithoutBlock> expr; // inlined from Statements + + Location locus; + + std::string as_string () const override; + + // Returns whether the block contains statements. + bool has_statements () const { return !statements.empty (); } + + // Returns whether the block contains an expression + bool has_expr () const { return expr != nullptr; } + + BlockExpr (Analysis::NodeMapping mappings, + 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 (mappings), 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 != nullptr) + expr = other.expr->clone_expr_without_block (); + + statements.reserve (other.statements.size ()); + for (const auto &e : other.statements) + statements.push_back (e->clone_stmt ()); + } + + // 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; + + 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 (); } + + void accept_vis (HIRVisitor &vis) override; + + void iterate_stmts (std::function<bool (Stmt *)> cb) + { + for (auto it = statements.begin (); it != statements.end (); it++) + { + if (!cb (it->get ())) + return; + } + } + + Location get_closing_locus () + { + if (statements.size () == 0) + return get_locus (); + + return statements[statements.size () - 1]->get_locus_slow (); + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + BlockExpr *clone_expr_impl () const override + { + return clone_block_expr_impl (); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + BlockExpr *clone_expr_with_block_impl () const override + { + return clone_block_expr_impl (); + } + + /* 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 HIR node +class ClosureExprInnerTyped : public ClosureExpr +{ + std::unique_ptr<Type> return_type; + std::unique_ptr<BlockExpr> + expr; // only used because may be polymorphic in future + +public: + std::string as_string () const override; + + // Constructor potentially with a move + ClosureExprInnerTyped (Analysis::NodeMapping mappings, + 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 (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ClosureExprInnerTyped *clone_expr_impl () const override + { + return new ClosureExprInnerTyped (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ClosureExprInnerTyped *clone_expr_without_block_impl () const override + { + return new ClosureExprInnerTyped (*this); + } +}; + +// HIR node representing continue expression within loops +class ContinueExpr : public ExprWithoutBlock +{ + // bool has_label; + Lifetime label; + Location locus; + +public: + std::string as_string () const override; + + // Returns true if the continue expr has a label. + bool has_label () const { return !label.is_error (); } + + // Constructor for a ContinueExpr with a label. + ContinueExpr (Analysis::NodeMapping mappings, Location locus, + Lifetime label = Lifetime::error (), + std::vector<Attribute> outer_attribs + = std::vector<Attribute> ()) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attribs)), + label (std::move (label)), locus (locus) + {} + + Location get_locus () const { return locus; } + Location get_locus_slow () const override { return get_locus (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ContinueExpr *clone_expr_impl () const override + { + return new ContinueExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ContinueExpr *clone_expr_without_block_impl () const override + { + return new ContinueExpr (*this); + } +}; +// TODO: merge "break" and "continue"? Or even merge in "return"? + +// HIR node representing break expression within loops +class BreakExpr : public ExprWithoutBlock +{ + // bool has_label; + Lifetime label; + + // bool has_break_expr; + std::unique_ptr<Expr> break_expr; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether the break expression has a label or not. + bool has_label () const { return !label.is_error (); } + + /* Returns whether the break expression has an expression used in the break or + * not. */ + bool has_break_expr () const { return break_expr != nullptr; } + + // Constructor for a break expression + BreakExpr (Analysis::NodeMapping mappings, Location locus, + Lifetime break_label = Lifetime::error (), + std::unique_ptr<Expr> expr_in_break = nullptr, + std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) + : ExprWithoutBlock (std::move (mappings), 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 != nullptr) + break_expr = other.break_expr->clone_expr (); + } + + // 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + BreakExpr *clone_expr_impl () const override { return new BreakExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + BreakExpr *clone_expr_without_block_impl () const override + { + return new BreakExpr (*this); + } +}; + +// Base range expression HIR node object - abstract +class RangeExpr : public ExprWithoutBlock +{ + Location locus; + +protected: + // outer attributes not allowed before range expressions + RangeExpr (Analysis::NodeMapping mappings, Location locus) + : ExprWithoutBlock (std::move (mappings), 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 HIR node object +// aka RangeExpr; constructs a std::ops::Range object +class RangeFromToExpr : public RangeExpr +{ + std::unique_ptr<Expr> from; + std::unique_ptr<Expr> to; + +public: + std::string as_string () const override; + + RangeFromToExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> range_from, + std::unique_ptr<Expr> range_to, Location locus) + : RangeExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromToExpr *clone_expr_impl () const override + { + return new RangeFromToExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromToExpr *clone_expr_without_block_impl () const override + { + return new RangeFromToExpr (*this); + } +}; + +// Range from (inclusive) expression HIR node object +// constructs a std::ops::RangeFrom object +class RangeFromExpr : public RangeExpr +{ + std::unique_ptr<Expr> from; + +public: + std::string as_string () const override; + + RangeFromExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> range_from, Location locus) + : RangeExpr (std::move (mappings), locus), from (std::move (range_from)) + {} + + // Copy constructor with clone + RangeFromExpr (RangeFromExpr const &other) + : RangeExpr (other), from (other.from->clone_expr ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromExpr *clone_expr_impl () const override + { + return new RangeFromExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromExpr *clone_expr_without_block_impl () const override + { + return new RangeFromExpr (*this); + } +}; + +// Range to (exclusive) expression HIR node object +// constructs a std::ops::RangeTo object +class RangeToExpr : public RangeExpr +{ + std::unique_ptr<Expr> to; + +public: + std::string as_string () const override; + + // outer attributes not allowed + RangeToExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> range_to, + Location locus) + : RangeExpr (std::move (mappings), locus), to (std::move (range_to)) + {} + + // Copy constructor with clone + RangeToExpr (RangeToExpr const &other) + : RangeExpr (other), to (other.to->clone_expr ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeToExpr *clone_expr_impl () const override + { + return new RangeToExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeToExpr *clone_expr_without_block_impl () const override + { + return new RangeToExpr (*this); + } +}; + +// Full range expression HIR node object +// constructs a std::ops::RangeFull object +class RangeFullExpr : public RangeExpr +{ +public: + std::string as_string () const override; + + RangeFullExpr (Analysis::NodeMapping mappings, Location locus) + : RangeExpr (std::move (mappings), locus) + {} + // outer attributes not allowed + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFullExpr *clone_expr_impl () const override + { + return new RangeFullExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFullExpr *clone_expr_without_block_impl () const override + { + return new RangeFullExpr (*this); + } +}; + +// Range from (inclusive) and to (inclusive) expression HIR node object +// aka RangeInclusiveExpr; constructs a std::ops::RangeInclusive object +class RangeFromToInclExpr : public RangeExpr +{ + std::unique_ptr<Expr> from; + std::unique_ptr<Expr> to; + +public: + std::string as_string () const override; + + RangeFromToInclExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> range_from, + std::unique_ptr<Expr> range_to, Location locus) + : RangeExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromToInclExpr *clone_expr_impl () const override + { + return new RangeFromToInclExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeFromToInclExpr *clone_expr_without_block_impl () const override + { + return new RangeFromToInclExpr (*this); + } +}; + +// Range to (inclusive) expression HIR node object +// aka RangeToInclusiveExpr; constructs a std::ops::RangeToInclusive object +class RangeToInclExpr : public RangeExpr +{ + std::unique_ptr<Expr> to; + +public: + std::string as_string () const override; + + RangeToInclExpr (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> range_to, Location locus) + : RangeExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeToInclExpr *clone_expr_impl () const override + { + return new RangeToInclExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangeToInclExpr *clone_expr_without_block_impl () const override + { + return new RangeToInclExpr (*this); + } +}; + +// Return expression HIR node representation +class ReturnExpr : public ExprWithoutBlock +{ +public: + std::unique_ptr<Expr> return_expr; + + Location locus; + + std::string as_string () const override; + + /* Returns whether the object has an expression returned (i.e. not void return + * type). */ + bool has_return_expr () const { return return_expr != nullptr; } + + // Constructor for ReturnExpr. + ReturnExpr (Analysis::NodeMapping mappings, Location locus, + std::unique_ptr<Expr> returned_expr = nullptr, + std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) + : ExprWithoutBlock (std::move (mappings), 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 != nullptr) + return_expr = other.return_expr->clone_expr (); + } + + // 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 (); } + + void accept_vis (HIRVisitor &vis) override; + + Expr *get_expr () { return return_expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ReturnExpr *clone_expr_impl () const override + { + return new ReturnExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ReturnExpr *clone_expr_without_block_impl () const override + { + return new ReturnExpr (*this); + } +}; + +// Forward decl - defined in rust-macro.h +class MacroInvocation; + +// An unsafe block HIR node +class UnsafeBlockExpr : public ExprWithBlock +{ + // Or just have it extend BlockExpr + std::unique_ptr<BlockExpr> expr; + + Location locus; + +public: + std::string as_string () const override; + + UnsafeBlockExpr (Analysis::NodeMapping mappings, + std::unique_ptr<BlockExpr> block_expr, + std::vector<Attribute> outer_attribs, Location locus) + : ExprWithBlock (std::move (mappings), 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) + {} + + // 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + UnsafeBlockExpr *clone_expr_impl () const override + { + return new UnsafeBlockExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + UnsafeBlockExpr *clone_expr_with_block_impl () const override + { + return new UnsafeBlockExpr (*this); + } +}; + +// Loop label expression HIR 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. + 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 HIR node - aka LoopExpr +class BaseLoopExpr : public ExprWithBlock +{ +protected: + // protected to allow subclasses better use of them + // bool has_loop_label; + LoopLabel loop_label; + + std::unique_ptr<BlockExpr> loop_block; + +private: + Location locus; + +protected: + // Constructor for BaseLoopExpr + BaseLoopExpr (Analysis::NodeMapping mappings, + std::unique_ptr<BlockExpr> loop_block, Location locus, + LoopLabel loop_label = LoopLabel::error (), + std::vector<Attribute> outer_attribs + = std::vector<Attribute> ()) + : ExprWithBlock (std::move (mappings), 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) + {} + + // 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: + 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) HIR node +class LoopExpr : public BaseLoopExpr +{ +public: + std::string as_string () const override; + + // Constructor for LoopExpr + LoopExpr (Analysis::NodeMapping mappings, + std::unique_ptr<BlockExpr> loop_block, Location locus, + LoopLabel loop_label = LoopLabel::error (), + std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) + : BaseLoopExpr (std::move (mappings), std::move (loop_block), locus, + std::move (loop_label), std::move (outer_attribs)) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + LoopExpr *clone_expr_impl () const override { return new LoopExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + LoopExpr *clone_expr_with_block_impl () const override + { + return new LoopExpr (*this); + } +}; + +// While loop expression HIR node (predicate loop) +class WhileLoopExpr : public BaseLoopExpr +{ + std::unique_ptr<Expr> condition; + +public: + std::string as_string () const override; + + // Constructor for while loop with loop label + WhileLoopExpr (Analysis::NodeMapping mappings, + 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 (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + WhileLoopExpr *clone_expr_impl () const override + { + return new WhileLoopExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + WhileLoopExpr *clone_expr_with_block_impl () const override + { + return new WhileLoopExpr (*this); + } +}; + +// While let loop expression HIR node (predicate pattern loop) +class WhileLetLoopExpr : public BaseLoopExpr +{ + // MatchArmPatterns patterns; + std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined + std::unique_ptr<Expr> condition; + +public: + std::string as_string () const override; + + // Constructor with a loop label + WhileLetLoopExpr (Analysis::NodeMapping mappings, + 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 (mappings), 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 ()) + { + 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 ()); + } + + // 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; + + 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + WhileLetLoopExpr *clone_expr_impl () const override + { + return new WhileLetLoopExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + WhileLetLoopExpr *clone_expr_with_block_impl () const override + { + return new WhileLetLoopExpr (*this); + } +}; + +// For loop expression HIR node (iterator loop) +class ForLoopExpr : public BaseLoopExpr +{ + std::unique_ptr<Pattern> pattern; + std::unique_ptr<Expr> iterator_expr; + +public: + std::string as_string () const override; + + // Constructor with loop label + ForLoopExpr (Analysis::NodeMapping mappings, + 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 (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ForLoopExpr *clone_expr_impl () const override + { + return new ForLoopExpr (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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" HIR node +class IfExpr : public ExprWithBlock +{ + std::unique_ptr<Expr> condition; + std::unique_ptr<BlockExpr> if_block; + + Location locus; + +public: + std::string as_string () const override; + + IfExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> condition, + std::unique_ptr<BlockExpr> if_block, Location locus) + : ExprWithBlock (std::move (mappings), 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) + {} + + // 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 HIRs 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 (); } + + void accept_vis (HIRVisitor &vis) override; + + void vis_if_condition (HIRVisitor &vis) { condition->accept_vis (vis); } + void vis_if_block (HIRVisitor &vis) { if_block->accept_vis (vis); } + + Expr *get_if_condition () { return condition.get (); } + BlockExpr *get_if_block () { return if_block.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + IfExpr *clone_expr_with_block_impl () const override + { + return new IfExpr (*this); + } +}; + +// If expression with an ending "else" expression HIR node (trailing) +class IfExprConseqElse : public IfExpr +{ + std::unique_ptr<BlockExpr> else_block; + +public: + std::string as_string () const override; + + IfExprConseqElse (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> condition, + std::unique_ptr<BlockExpr> if_block, + std::unique_ptr<BlockExpr> else_block, Location locus) + : IfExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + + void vis_else_block (HIRVisitor &vis) { else_block->accept_vis (vis); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqElse *clone_expr_impl () const override + { + return new IfExprConseqElse (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + IfExprConseqElse *clone_if_expr_impl () const override + { + return new IfExprConseqElse (*this); + } +}; + +// If expression with an ending "else if" expression HIR node +class IfExprConseqIf : public IfExpr +{ + std::unique_ptr<IfExpr> conseq_if_expr; + +public: + std::string as_string () const override; + + IfExprConseqIf (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> condition, + std::unique_ptr<BlockExpr> if_block, + std::unique_ptr<IfExpr> conseq_if_expr, Location locus) + : IfExpr (std::move (mappings), std::move (condition), std::move (if_block), + locus), + conseq_if_expr (std::move (conseq_if_expr)) + {} + // outer attributes not allowed + + // Copy constructor with clone + IfExprConseqIf (IfExprConseqIf const &other) + : IfExpr (other), conseq_if_expr (other.conseq_if_expr->clone_if_expr ()) + {} + + // 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(); + conseq_if_expr = other.conseq_if_expr->clone_if_expr (); + + return *this; + } + + // move constructors + IfExprConseqIf (IfExprConseqIf &&other) = default; + IfExprConseqIf &operator= (IfExprConseqIf &&other) = default; + + void accept_vis (HIRVisitor &vis) override; + + void vis_conseq_if_expr (HIRVisitor &vis) + { + conseq_if_expr->accept_vis (vis); + } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqIf *clone_expr_impl () const override + { + return new IfExprConseqIf (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + IfExprConseqIf *clone_if_expr_impl () const override + { + return new IfExprConseqIf (*this); + } +}; + +// Basic "if let" expression HIR node with no else +class IfLetExpr : public ExprWithBlock +{ + // MatchArmPatterns patterns; + std::vector<std::unique_ptr<Pattern> > match_arm_patterns; // inlined + std::unique_ptr<Expr> value; + std::unique_ptr<BlockExpr> if_block; + + Location locus; + +public: + std::string as_string () const override; + + IfLetExpr (Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<Pattern> > match_arm_patterns, + std::unique_ptr<Expr> value, std::unique_ptr<BlockExpr> if_block, + Location locus) + : ExprWithBlock (std::move (mappings), 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) + { + 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 ()); + } + + // 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; + + 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExpr *clone_expr_impl () const override { return new IfLetExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 HIR node +class IfExprConseqIfLet : public IfExpr +{ + std::unique_ptr<IfLetExpr> if_let_expr; + +public: + std::string as_string () const override; + + IfExprConseqIfLet (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> condition, + std::unique_ptr<BlockExpr> if_block, + std::unique_ptr<IfLetExpr> conseq_if_let_expr, + Location locus) + : IfExpr (std::move (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfExprConseqIfLet *clone_expr_impl () const override + { + return new IfExprConseqIfLet (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + IfExprConseqIfLet *clone_if_expr_impl () const override + { + return new IfExprConseqIfLet (*this); + } +}; + +/* HIR node representing "if let" expression with an "else" expression at the + * end */ +class IfLetExprConseqElse : public IfLetExpr +{ + std::unique_ptr<BlockExpr> else_block; + +public: + std::string as_string () const override; + + IfLetExprConseqElse ( + Analysis::NodeMapping mappings, + 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 (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqElse *clone_expr_impl () const override + { + return new IfLetExprConseqElse (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + IfLetExprConseqElse *clone_if_let_expr_impl () const override + { + return new IfLetExprConseqElse (*this); + } +}; + +/* HIR node representing "if let" expression with an "else if" expression at the + * end */ +class IfLetExprConseqIf : public IfLetExpr +{ + std::unique_ptr<IfExpr> if_expr; + +public: + std::string as_string () const override; + + IfLetExprConseqIf (Analysis::NodeMapping mappings, + 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 (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqIf *clone_expr_impl () const override + { + return new IfLetExprConseqIf (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + IfLetExprConseqIf *clone_if_let_expr_impl () const override + { + return new IfLetExprConseqIf (*this); + } +}; + +/* HIR node representing "if let" expression with an "else if let" expression at + * the end */ +class IfLetExprConseqIfLet : public IfLetExpr +{ + std::unique_ptr<IfLetExpr> if_let_expr; + +public: + std::string as_string () const override; + + IfLetExprConseqIfLet ( + Analysis::NodeMapping mappings, + 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 (mappings), 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 ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IfLetExprConseqIfLet *clone_expr_impl () const override + { + return new IfLetExprConseqIfLet (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + 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; + // inlined from MatchArmGuard + std::unique_ptr<Expr> guard_expr; + + // TODO: should this store location data? + +public: + // Returns whether the MatchArm has a match arm guard expression + bool has_match_arm_guard () const { return guard_expr != nullptr; } + + // Constructor for match arm with a guard expression + MatchArm (std::vector<std::unique_ptr<Pattern> > match_arm_patterns, + std::unique_ptr<Expr> guard_expr = nullptr, + 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) : outer_attrs (other.outer_attrs) + { + // guard to protect from null pointer dereference + if (other.guard_expr != nullptr) + guard_expr = other.guard_expr->clone_expr (); + + 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 ()); + } + + ~MatchArm () = default; + + // Overload assignment operator to clone + MatchArm &operator= (MatchArm const &other) + { + outer_attrs = other.outer_attrs; + + if (other.guard_expr != nullptr) + guard_expr = other.guard_expr->clone_expr (); + + 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. + 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 + { + return std::unique_ptr<MatchCase> (clone_match_case_impl ()); + } + + virtual std::string as_string () const; + + virtual void accept_vis (HIRVisitor &vis) = 0; +}; +*/ + +/* A "match case" - a correlated match arm and resulting expression. Not + * abstract. */ +struct MatchCase +{ +private: + MatchArm arm; + std::unique_ptr<Expr> expr; + + /* TODO: does whether trailing comma exists need to be stored? currently + * assuming it is only syntactical and has no effect on meaning. */ + +public: + MatchCase (MatchArm arm, std::unique_ptr<Expr> expr) + : arm (std::move (arm)), expr (std::move (expr)) + {} + + MatchCase (const MatchCase &other) + : arm (other.arm), expr (other.expr->clone_expr ()) + {} + + MatchCase &operator= (const MatchCase &other) + { + arm = other.arm; + expr = other.expr->clone_expr (); + + return *this; + } + + MatchCase (MatchCase &&other) = default; + MatchCase &operator= (MatchCase &&other) = default; + + ~MatchCase () = default; + + std::string as_string () const; +}; + +#if 0 +// Block expression match case +class MatchCaseBlockExpr : public MatchCase +{ + std::unique_ptr<BlockExpr> block_expr; + + // TODO: should this store location data? + +public: + 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 ()) + {} + + // 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + MatchCaseBlockExpr *clone_match_case_impl () const override + { + return new MatchCaseBlockExpr (*this); + } +}; + +// Expression (except block expression) match case +class MatchCaseExpr : public MatchCase +{ + std::unique_ptr<Expr> expr; + + // TODO: should this store location data? + +public: + 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 ()) + {} + + // 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + MatchCaseExpr *clone_match_case_impl () const override + { + return new MatchCaseExpr (*this); + } +}; +#endif + +// Match expression HIR node +class MatchExpr : public ExprWithBlock +{ + 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 + std::vector<MatchCase> match_arms; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether the match expression has any match arms. + bool has_match_arms () const { return !match_arms.empty (); } + + MatchExpr (Analysis::NodeMapping mappings, std::unique_ptr<Expr> branch_value, + // std::vector<std::unique_ptr<MatchCase> > match_arms, + std::vector<MatchCase> match_arms, + std::vector<Attribute> inner_attrs, + std::vector<Attribute> outer_attrs, Location locus) + : ExprWithBlock (std::move (mappings), 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 ()), + inner_attrs (other.inner_attrs), match_arms (other.match_arms), + locus (other.locus) + { + /*match_arms.reserve (other.match_arms.size ()); + for (const auto &e : other.match_arms) + match_arms.push_back (e->clone_match_case ());*/ + } + + // Overloaded assignment operator to clone due to unique_ptr + MatchExpr &operator= (MatchExpr const &other) + { + ExprWithBlock::operator= (other); + branch_value = other.branch_value->clone_expr (); + inner_attrs = other.inner_attrs; + match_arms = other.match_arms; + // outer_attrs = other.outer_attrs; + locus = other.locus; + + /*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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + MatchExpr *clone_expr_impl () const override { return new MatchExpr (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MatchExpr *clone_expr_with_block_impl () const override + { + return new MatchExpr (*this); + } +}; + +// Await expression HIR 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 (Analysis::NodeMapping mappings, std::unique_ptr<Expr> awaited_expr, + std::vector<Attribute> outer_attrs, Location locus) + : ExprWithoutBlock (std::move (mappings), 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) + {} + + // 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 override; + + Location get_locus () const { return locus; } + Location get_locus_slow () const override { return get_locus (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + AwaitExpr *clone_expr_without_block_impl () const override + { + return new AwaitExpr (*this); + } +}; + +// Async block expression HIR 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 (Analysis::NodeMapping mappings, + std::unique_ptr<BlockExpr> block_expr, bool has_move, + std::vector<Attribute> outer_attrs, Location locus) + : ExprWithBlock (std::move (mappings), 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) + {} + + // 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 override; + + Location get_locus () const { return locus; } + Location get_locus_slow () const override { return get_locus (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + AsyncBlockExpr *clone_expr_with_block_impl () const override + { + return new AsyncBlockExpr (*this); + } +}; +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-full-decls.h b/gcc/rust/hir/tree/rust-hir-full-decls.h new file mode 100644 index 0000000..02b9f03 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-full-decls.h @@ -0,0 +1,285 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_FULL_DECLS_H +#define RUST_HIR_FULL_DECLS_H +// Forward declarations for all HIR classes. Useful for not having to include +// all definitions. + +namespace Rust { +namespace HIR { +// rust-ast.h +class AttrInput; +class TokenTree; +class MacroMatch; +class Token; +struct Literal; +class DelimTokenTree; +class PathSegment; +class SimplePathSegment; +class SimplePath; +struct Attribute; +class MetaItemInner; +class AttrInputMetaItemContainer; +class MetaItem; +class Stmt; +class Item; +class Expr; +class ExprWithoutBlock; +class IdentifierExpr; +class Pattern; +class Type; +class TypeNoBounds; +class TypeParamBound; +class Lifetime; +class GenericParam; +class LifetimeParam; +class MacroItem; +class TraitItem; +class InherentImplItem; +class TraitImplItem; +class MacroInvocationSemi; +struct Crate; +class PathExpr; + +// rust-path.h +class PathIdentSegment; +struct GenericArgsBinding; +struct GenericArgs; +class PathExprSegment; +class PathPattern; +class PathInExpression; +class TypePathSegment; +class TypePathSegmentGeneric; +struct TypePathFunction; +class TypePathSegmentFunction; +class TypePath; +struct QualifiedPathType; +class QualifiedPathInExpression; +class QualifiedPathInType; + +// rust-expr.h +class ExprWithBlock; +class LiteralExpr; +class AttrInputLiteral; +class MetaItemLitExpr; +class MetaItemPathLit; +class OperatorExpr; +class BorrowExpr; +class DereferenceExpr; +class ErrorPropagationExpr; +class NegationExpr; +class ArithmeticOrLogicalExpr; +class ComparisonExpr; +class LazyBooleanExpr; +class TypeCastExpr; +class AssignmentExpr; +class CompoundAssignmentExpr; +class GroupedExpr; +class ArrayElems; +class ArrayElemsValues; +class ArrayElemsCopied; +class ArrayExpr; +class ArrayIndexExpr; +class TupleExpr; +class TupleIndexExpr; +class StructExpr; +class StructExprStruct; +struct StructBase; +class StructExprField; +class StructExprFieldIdentifier; +class StructExprFieldWithVal; +class StructExprFieldIdentifierValue; +class StructExprFieldIndexValue; +class StructExprStructFields; +class StructExprStructBase; +class StructExprTuple; +class StructExprUnit; +class EnumVariantExpr; +class EnumExprField; +class EnumExprFieldIdentifier; +class EnumExprFieldWithVal; +class EnumExprFieldIdentifierValue; +class EnumExprFieldIndexValue; +class EnumExprStruct; +class EnumExprTuple; +class EnumExprFieldless; +class CallExpr; +class MethodCallExpr; +class FieldAccessExpr; +struct ClosureParam; +class ClosureExpr; +class ClosureExprInner; +class BlockExpr; +class ClosureExprInnerTyped; +class ContinueExpr; +class BreakExpr; +class RangeExpr; +class RangeFromToExpr; +class RangeFromExpr; +class RangeToExpr; +class RangeFullExpr; +class RangeFromToInclExpr; +class RangeToInclExpr; +class ReturnExpr; +class UnsafeBlockExpr; +class LoopLabel; +class BaseLoopExpr; +class LoopExpr; +class WhileLoopExpr; +class WhileLetLoopExpr; +class ForLoopExpr; +class IfExpr; +class IfExprConseqElse; +class IfExprConseqIf; +class IfLetExpr; +class IfExprConseqIfLet; +class IfLetExprConseqElse; +class IfLetExprConseqIf; +class IfLetExprConseqIfLet; +struct MatchArm; +// class MatchCase; +// class MatchCaseBlockExpr; +// class MatchCaseExpr; +struct MatchCase; +class MatchExpr; +class AwaitExpr; +class AsyncBlockExpr; + +// rust-stmt.h +class EmptyStmt; +class LetStmt; +class ExprStmt; +class ExprStmtWithoutBlock; +class ExprStmtWithBlock; + +// rust-item.h +class TypeParam; +class WhereClauseItem; +class LifetimeWhereClauseItem; +class TypeBoundWhereClauseItem; +struct WhereClause; +struct SelfParam; +struct FunctionQualifiers; +struct FunctionParam; +struct Visibility; +class Method; +class VisItem; +class Module; +class ModuleBodied; +class ModuleNoBody; +class ExternCrate; +class UseTree; +class UseTreeGlob; +class UseTreeList; +class UseTreeRebind; +class UseDeclaration; +class Function; +class TypeAlias; +class Struct; +struct StructField; +class StructStruct; +struct TupleField; +class TupleStruct; +class EnumItem; +class EnumItemTuple; +class EnumItemStruct; +class EnumItemDiscriminant; +class Enum; +class Union; +class ConstantItem; +class StaticItem; +struct TraitFunctionDecl; +class TraitItemFunc; +struct TraitMethodDecl; +class TraitItemMethod; +class TraitItemConst; +class TraitItemType; +class Trait; +class Impl; +class InherentImpl; +class TraitImpl; +class ExternalItem; +class ExternalStaticItem; +struct NamedFunctionParam; +class ExternalFunctionItem; +class ExternBlock; + +// rust-macro.h +class MacroMatchFragment; +class MacroMatchRepetition; +class MacroMatcher; +struct MacroTranscriber; +struct MacroRule; +class MacroRulesDefinition; +class MacroInvocation; +class MetaItemPath; +class MetaItemSeq; +class MetaWord; +class MetaNameValueStr; +class MetaListPaths; +class MetaListNameValueStr; + +// rust-pattern.h +class LiteralPattern; +class IdentifierPattern; +class WildcardPattern; +class RangePatternBound; +class RangePatternBoundLiteral; +class RangePatternBoundPath; +class RangePatternBoundQualPath; +class RangePattern; +class ReferencePattern; +struct StructPatternEtc; +class StructPatternField; +class StructPatternFieldTuplePat; +class StructPatternFieldIdentPat; +class StructPatternFieldIdent; +struct StructPatternElements; +class StructPattern; +class TupleStructItems; +class TupleStructItemsNoRange; +class TupleStructItemsRange; +class TupleStructPattern; +class TuplePatternItems; +class TuplePatternItemsMultiple; +class TuplePatternItemsRanged; +class TuplePattern; +class GroupedPattern; +class SlicePattern; + +// rust-type.h +class TraitBound; +class ImplTraitType; +class TraitObjectType; +class ParenthesisedType; +class ImplTraitTypeOneBound; +class TraitObjectTypeOneBound; +class TupleType; +class NeverType; +class RawPointerType; +class ReferenceType; +class ArrayType; +class SliceType; +class InferredType; +struct MaybeNamedParam; +class BareFunctionType; +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-full-test.cc b/gcc/rust/hir/tree/rust-hir-full-test.cc new file mode 100644 index 0000000..0a87d25 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-full-test.cc @@ -0,0 +1,6100 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-hir-full.h" +#include "rust-hir-visitor.h" +#include "rust-diagnostics.h" + +/* Compilation unit used for various HIR-related functions that would make + * the headers too long if they were defined inline and don't receive any + * benefits from being defined inline because they are virtual. Also used + * for various other stuff. */ + +namespace Rust { +namespace HIR { + +enum indent_mode +{ + enter, + out, + stay +}; + +std::string +indent_spaces (enum indent_mode mode) +{ + static int indent = 0; + std::string str = ""; + if (out == mode) + indent--; + for (int i = 0; i < indent; i++) + str += " "; + if (enter == mode) + indent++; + + return str; +} + +// Gets a string in a certain delim type. +std::string +get_string_in_delims (std::string str_input, DelimType delim_type) +{ + switch (delim_type) + { + case PARENS: + return "(" + str_input + ")"; + case SQUARE: + return "[" + str_input + "]"; + case CURLY: + return "{" + str_input + "}"; + default: + return "ERROR-MARK-STRING (delims)"; + } + gcc_unreachable (); +} + +// Converts a frag spec enum item to a string form. +std::string +frag_spec_to_str (MacroFragSpec frag_spec) +{ + switch (frag_spec) + { + case BLOCK: + return "block"; + case EXPR: + return "expr"; + case IDENT: + return "ident"; + case ITEM: + return "item"; + case LIFETIME: + return "lifetime"; + case LITERAL: + return "literal"; + case META: + return "meta"; + case PAT: + return "pat"; + case PATH: + return "path"; + case STMT: + return "stmt"; + case TT: + return "tt"; + case TY: + return "ty"; + case VIS: + return "vis"; + case INVALID: + return "INVALID_FRAG_SPEC"; + default: + return "ERROR_MARK_STRING - unknown frag spec"; + } +} + +std::string +Crate::as_string () const +{ + std::string str ("HIR::Crate: "); + // add utf8bom and shebang + if (has_utf8bom) + { + str += "\n has utf8bom"; + } + if (has_shebang) + { + str += "\n has shebang"; + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // items + str += "\n items: "; + if (items.empty ()) + { + str += "none"; + } + else + { + for (const auto &item : items) + { + // DEBUG: null pointer check + if (item == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - " + "null pointer item in crate."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + item->as_string (); + } + } + + return str + "\n::" + get_mappings ().as_string () + "\n"; +} + +std::string +Attribute::as_string () const +{ + std::string path_str = path.as_string (); + if (attr_input == nullptr) + { + return path_str; + } + else + { + return path_str + attr_input->as_string (); + } +} + +std::string +DelimTokenTree::as_string () const +{ + std::string start_delim; + std::string end_delim; + switch (delim_type) + { + case PARENS: + start_delim = "("; + end_delim = ")"; + break; + case SQUARE: + start_delim = "["; + end_delim = "]"; + break; + case CURLY: + start_delim = "{"; + end_delim = "}"; + break; + default: + fprintf (stderr, "Invalid delimiter type, " + "Should be PARENS, SQUARE, or CURLY."); + return "Invalid delimiter type"; + } + std::string str = start_delim; + if (!token_trees.empty ()) + { + for (const auto &tree : token_trees) + { + // DEBUG: null pointer check + if (tree == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "token tree in delim token tree."); + return "nullptr_POINTER_MARK"; + } + + str += tree->as_string (); + } + } + str += end_delim; + + return str; +} + +std::string +Token::as_string () const +{ + /* FIXME: only works when not identifier or literal or whatever, i.e. when + * doesn't store string value */ + // return get_token_description(token_id); + + // maybe fixed - stores everything as string though, so storage-inefficient + std::string quote = is_string_lit () ? "\"" : ""; + return quote + str + quote; +} + +std::string +SimplePathSegment::as_string () const +{ + return segment_name; +} + +std::string +SimplePath::as_string () const +{ + std::string path; + if (has_opening_scope_resolution) + { + path = "::"; + } + + // crappy hack because doing proper for loop would be more code + bool first_time = true; + for (const auto &segment : segments) + { + if (first_time) + { + path += segment.as_string (); + first_time = false; + } + else + { + path += "::" + segment.as_string (); + } + + // DEBUG: remove later. Checks for path error. + if (segment.is_error ()) + { + fprintf (stderr, + "segment in path is error - this should've been filtered " + "out. first segment " + "was '%s' \n", + segments.at (0).as_string ().c_str ()); + } + } + + return path; +} + +std::string +Visibility::as_string () const +{ + switch (public_vis_type) + { + case NONE: + return std::string ("pub"); + case CRATE: + return std::string ("ub(crate)"); + case SELF: + return std::string ("pub(self)"); + case SUPER: + return std::string ("pub(super)"); + case IN_PATH: + return std::string ("pub(in ") + in_path.as_string () + std::string (")"); + default: + gcc_unreachable (); + } +} + +// Creates a string that reflects the visibility stored. +std::string +VisItem::as_string () const +{ + // FIXME: can't do formatting on string to make identation occur. + std::string str = Item::as_string (); + + if (has_visibility ()) + { + str = visibility.as_string () + " "; + } + + return str; +} + +// Creates a string that reflects the outer attributes stored. +std::string +Item::as_string () const +{ + std::string str; + + if (!outer_attrs.empty ()) + { + for (const auto &attr : outer_attrs) + { + str += attr.as_string () + "\n"; + } + } + + return str; +} + +std::string +Module::as_string () const +{ + std::string vis_item = VisItem::as_string (); + + return vis_item + "mod " + module_name; +} + +std::string +ModuleBodied::as_string () const +{ + // get module string for "[vis] mod [name]" + std::string str = Module::as_string (); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // items + str += "\n items: "; + if (items.empty ()) + { + str += "none"; + } + else + { + for (const auto &item : items) + { + // DEBUG: null pointer check + if (item == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - " + "null pointer item in crate."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + item->as_string (); + } + } + + return str + "\n"; +} + +std::string +ModuleNoBody::as_string () const +{ + std::string str = Module::as_string (); + + str += "\n no body (reference to external file)"; + + return str + "\n"; +} + +std::string +StaticItem::as_string () const +{ + std::string str = VisItem::as_string (); + + str += indent_spaces (stay) + "static"; + + if (has_mut) + { + str += " mut"; + } + + str += name; + + // DEBUG: null pointer check + if (type == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - null " + "pointer type in static item."); + return "nullptr_POINTER_MARK"; + } + str += "\n" + indent_spaces (stay) + "Type: " + type->as_string (); + + // DEBUG: null pointer check + if (expr == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - null " + "pointer expr in static item."); + return "nullptr_POINTER_MARK"; + } + str += "\n" + indent_spaces (stay) + "Expression: " + expr->as_string (); + + return str + "\n"; +} + +std::string +ExternCrate::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "extern crate " + referenced_crate; + + if (has_as_clause ()) + { + str += " as " + as_clause_name; + } + + return str; +} + +std::string +TupleStruct::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "struct " + struct_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in enum."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + // tuple fields + str += "\n Tuple fields: "; + if (fields.empty ()) + { + str += "none"; + } + else + { + for (const auto &field : fields) + { + str += "\n " + field.as_string (); + } + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +ConstantItem::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "const " + identifier; + + // DEBUG: null pointer check + if (type == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - null " + "pointer type in const item."); + return "nullptr_POINTER_MARK"; + } + str += "\n Type: " + type->as_string (); + + // DEBUG: null pointer check + if (const_expr == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - null " + "pointer expr in const item."); + return "nullptr_POINTER_MARK"; + } + str += "\n Expression: " + const_expr->as_string (); + + return str + "\n"; +} + +std::string +InherentImpl::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "impl "; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in inherent impl."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Type: " + trait_type->as_string (); + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // inherent impl items + str += "\n Inherent impl items: "; + if (!has_impl_items ()) + { + str += "none"; + } + else + { + for (const auto &item : impl_items) + { + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +Method::as_string () const +{ + std::string str ("Method: \n "); + + str += vis.as_string () + " " + qualifiers.as_string (); + + str += " fn " + method_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in method."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Self param: " + self_param.as_string (); + + str += "\n Function params: "; + if (function_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : function_params) + { + str += "\n " + param.as_string (); + } + } + + str += "\n Return type: "; + if (has_return_type ()) + { + str += return_type->as_string (); + } + else + { + str += "none (void)"; + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + str += "\n Block expr (body): \n "; + str += expr->as_string (); + + return str; +} + +std::string +StructStruct::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "struct " + struct_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in enum."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + // struct fields + str += "\n Struct fields: "; + if (is_unit) + { + str += "none (unit)"; + } + else if (fields.empty ()) + { + str += "none (non-unit)"; + } + else + { + for (const auto &field : fields) + { + str += "\n " + field.as_string (); + } + } + + return str; +} + +std::string +UseDeclaration::as_string () const +{ + std::string str = VisItem::as_string (); + + // DEBUG: null pointer check + if (use_tree == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer use tree in " + "use declaration."); + return "nullptr_POINTER_MARK"; + } + + str += "use " + use_tree->as_string (); + + return str; +} + +std::string +UseTreeGlob::as_string () const +{ + switch (glob_type) + { + case NO_PATH: + return "*"; + case GLOBAL: + return "::*"; + case PATH_PREFIXED: { + std::string path_str = path.as_string (); + return path_str + "::*"; + } + default: + // some kind of error + return "ERROR-PATH"; + } + gcc_unreachable (); +} + +std::string +UseTreeList::as_string () const +{ + std::string path_str; + switch (path_type) + { + case NO_PATH: + path_str = "{"; + break; + case GLOBAL: + path_str = "::{"; + break; + case PATH_PREFIXED: { + path_str = path.as_string () + "::{"; + break; + } + default: + // some kind of error + return "ERROR-PATH-LIST"; + } + + if (has_trees ()) + { + auto i = trees.begin (); + auto e = trees.end (); + + // DEBUG: null pointer check + if (*i == nullptr) + { + fprintf (stderr, + "something really terrible has gone wrong - null pointer " + "tree in use tree list."); + return "nullptr_POINTER_MARK"; + } + + for (; i != e; i++) + { + path_str += (*i)->as_string (); + if (e != i + 1) + path_str += ", "; + } + } + else + { + path_str += "none"; + } + + return path_str + "}"; +} + +std::string +UseTreeRebind::as_string () const +{ + std::string path_str = path.as_string (); + + switch (bind_type) + { + case NONE: + // nothing to add, just path + break; + case IDENTIFIER: + path_str += " as " + identifier; + break; + case WILDCARD: + path_str += " as _"; + break; + default: + // error + return "ERROR-PATH-REBIND"; + } + + return path_str; +} + +std::string +Enum::as_string () const +{ + std::string str = VisItem::as_string (); + str += enum_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in enum."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + // items + str += "\n Items: "; + if (items.empty ()) + { + str += "none"; + } + else + { + for (const auto &item : items) + { + // DEBUG: null pointer check + if (item == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "enum item in enum."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +Trait::as_string () const +{ + std::string str = VisItem::as_string (); + + if (has_unsafe) + { + str += "unsafe "; + } + + str += "trait " + name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in trait."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Type param bounds: "; + if (!has_type_param_bounds ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + // DEBUG: null pointer check + if (bound == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "type param bound in trait."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + bound->as_string (); + } + } + + str += "\n Where clause: "; + if (!has_where_clause ()) + { + str += "none"; + } + else + { + str += where_clause.as_string (); + } + + str += "\n Trait items: "; + if (!has_trait_items ()) + { + str += "none"; + } + else + { + for (const auto &item : trait_items) + { + // DEBUG: null pointer check + if (item == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "trait item in trait."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +Union::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "union " + union_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in union."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + // struct fields + str += "\n Struct fields (variants): "; + if (variants.empty ()) + { + str += "none"; + } + else + { + for (const auto &field : variants) + { + str += "\n " + field.as_string (); + } + } + + return str; +} + +std::string +Function::as_string () const +{ + std::string str = VisItem::as_string () + "\n"; + std::string qstr = qualifiers.as_string (); + if ("" != qstr) + str += qstr + " "; + + if (has_function_return_type ()) + { + // DEBUG: null pointer check + if (return_type == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer return " + "type in function."); + return "nullptr_POINTER_MARK"; + } + + str += return_type->as_string () + " "; + } + else + { + str += "void "; + } + + str += function_name; + + if (has_generics ()) + { + str += "<"; + + auto i = generic_params.begin (); + auto e = generic_params.end (); + + // DEBUG: null pointer check + if (i == e) + { + fprintf (stderr, + "something really terrible has gone wrong - null pointer " + "generic param in function item."); + return "nullptr_POINTER_MARK"; + } + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + str += ">"; + } + + if (has_function_params ()) + { + auto i = function_params.begin (); + auto e = function_params.end (); + str += "("; + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + str += ")"; + } + else + { + str += "()"; + } + + if (has_where_clause ()) + { + str += " where " + where_clause.as_string (); + } + + str += "\n"; + + // DEBUG: null pointer check + if (function_body == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer function " + "body in function."); + return "nullptr_POINTER_MARK"; + } + return str + function_body->as_string () + "::" + get_mappings ().as_string () + + "\n"; +} + +std::string +WhereClause::as_string () const +{ + // just print where clause items, don't mention "where" or "where clause" + std::string str; + + if (where_clause_items.empty ()) + { + str = "none"; + } + else + { + for (const auto &item : where_clause_items) + { + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +BlockExpr::as_string () const +{ + std::string istr = indent_spaces (enter); + std::string str = istr + "BlockExpr:\n" + istr; + // get outer attributes + str += "{\n" + indent_spaces (stay) + Expr::as_string (); + + // inner attributes + str += "\n" + indent_spaces (stay) + "inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n" + indent_spaces (stay) + attr.as_string (); + } + } + + // statements + str += "\n" + indent_spaces (stay) + "statements: "; + if (statements.empty ()) + { + str += "none"; + } + else + { + for (const auto &stmt : statements) + { + // DEBUG: null pointer check + if (stmt == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "stmt in block expr."); + return "nullptr_POINTER_MARK"; + } + + str += "\n" + indent_spaces (stay) + stmt->as_string (); + } + } + + // final expression + str += "\n" + indent_spaces (stay) + "final expression: "; + if (expr == nullptr) + { + str += "none"; + } + else + { + str += "\n" + expr->as_string (); + } + + str += "\n" + indent_spaces (out) + "}"; + return str; +} + +std::string +TraitImpl::as_string () const +{ + std::string str = VisItem::as_string (); + + if (has_unsafe) + { + str += "unsafe "; + } + + str += "impl "; + + // generic params + str += "\n Generic params: "; + if (!has_generics ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + str += "\n " + param->as_string (); + } + } + + str += "\n Has exclam: "; + if (has_exclam) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n TypePath (to trait): " + trait_path.as_string (); + + str += "\n Type (struct to impl on): " + trait_type->as_string (); + + str += "\n Where clause: "; + if (!has_where_clause ()) + { + str += "none"; + } + else + { + str += where_clause.as_string (); + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n trait impl items: "; + if (!has_impl_items ()) + { + str += "none"; + } + else + { + for (const auto &item : impl_items) + { + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +TypeAlias::as_string () const +{ + std::string str = VisItem::as_string (); + + str += " " + new_type_name; + + // generic params + str += "\n Generic params: "; + if (!has_generics ()) + { + str += "none"; + } + else + { + auto i = generic_params.begin (); + auto e = generic_params.end (); + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + } + + str += "\n Where clause: "; + if (!has_where_clause ()) + { + str += "none"; + } + else + { + str += where_clause.as_string (); + } + + str += "\n Type: " + existing_type->as_string (); + + return str; +} + +std::string +MacroInvocationSemi::as_string () const +{ + // get outer attrs + std::string str = MacroItem::as_string (); + + str += "\n" + path.as_string () + "!"; + + std::string tok_trees; + if (token_trees.empty ()) + { + tok_trees = "none"; + } + else + { + auto i = token_trees.begin (); + auto e = token_trees.end (); + + // DEBUG: null pointer check + if (i == e) + { + fprintf (stderr, + "something really terrible has gone wrong - null pointer " + "token tree in macro invocation semi."); + return "nullptr_POINTER_MARK"; + } + + std::string s; + for (; i != e; i++) + { + s += (*i)->as_string (); + if (e != i + 1) + s += ", "; + } + + tok_trees += get_string_in_delims (s, delim_type); + } + + return str; +} + +std::string +ExternBlock::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "extern "; + if (has_abi ()) + { + str += "\"" + abi + "\" "; + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n external items: "; + if (!has_extern_items ()) + { + str += "none"; + } + else + { + for (const auto &item : extern_items) + { + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +MacroRule::as_string () const +{ + std::string str ("Macro rule: "); + + str += "\n Matcher: \n "; + str += matcher.as_string (); + + str += "\n Transcriber: \n "; + str += transcriber.as_string (); + + return str; +} + +std::string +MacroRulesDefinition::as_string () const +{ + std::string str ("macro_rules!"); + + str += rule_name; + + str += "\n Macro rules: "; + if (rules.empty ()) + { + str += "none"; + } + else + { + for (const auto &rule : rules) + { + str += "\n " + rule.as_string (); + } + } + + str += "\n Delim type: "; + switch (delim_type) + { + case PARENS: + str += "parentheses"; + break; + case SQUARE: + str += "square"; + break; + case CURLY: + str += "curly"; + break; + default: + return "ERROR_MARK_STRING - delim type in macro invocation"; + } + + return str; +} + +std::string +MacroInvocation::as_string () const +{ + return "MacroInvocation: " + path.as_string () + "!" + + token_tree.as_string (); +} + +std::string +PathInExpression::as_string () const +{ + std::string str; + + if (has_opening_scope_resolution) + { + str = "::"; + } + + return str + PathPattern::as_string () + "::" + get_mappings ().as_string (); +} + +std::string +ExprStmtWithBlock::as_string () const +{ + std::string str = indent_spaces (enter) + "ExprStmtWithBlock: \n"; + + if (expr == nullptr) + { + str += "none (this should not happen and is an error)"; + } + else + { + indent_spaces (enter); + str += expr->as_string (); + indent_spaces (out); + } + + indent_spaces (out); + return str; +} + +std::string +ClosureParam::as_string () const +{ + std::string str (pattern->as_string ()); + + if (has_type_given ()) + { + str += " : " + type->as_string (); + } + + return str; +} + +std::string +ClosureExpr::as_string () const +{ + std::string str ("ClosureExpr:\n Has move: "); + if (has_move) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n Params: "; + if (params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : params) + { + str += "\n " + param.as_string (); + } + } + + return str; +} + +std::string +ClosureExprInnerTyped::as_string () const +{ + std::string str = ClosureExpr::as_string (); + + str += "\n Return type: " + return_type->as_string (); + + str += "\n Body: " + expr->as_string (); + + return str; +} + +std::string +PathPattern::as_string () const +{ + std::string str; + + for (const auto &segment : segments) + { + str += segment.as_string () + "::"; + } + + // basically a hack - remove last two characters of string (remove final ::) + str.erase (str.length () - 2); + + return str; +} + +std::string +QualifiedPathType::as_string () const +{ + std::string str ("<"); + str += type_to_invoke_on->as_string (); + + if (has_as_clause ()) + { + str += " as " + trait_path.as_string (); + } + + return str + ">"; +} + +std::string +QualifiedPathInExpression::as_string () const +{ + return path_type.as_string () + "::" + PathPattern::as_string (); +} + +std::string +BorrowExpr::as_string () const +{ + std::string str ("&"); + + if (double_borrow) + { + str += "&"; + } + + if (is_mut) + { + str += "mut "; + } + + str += main_or_left_expr->as_string (); + + return str; +} + +std::string +ReturnExpr::as_string () const +{ + std::string str ("return "); + + if (has_return_expr ()) + { + str += return_expr->as_string (); + } + + return str + "::" + get_mappings ().as_string (); +} + +std::string +GroupedExpr::as_string () const +{ + std::string str ("Grouped expr:"); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n Expr in parens: " + expr_in_parens->as_string (); + + return str; +} + +std::string +RangeToExpr::as_string () const +{ + return ".." + to->as_string (); +} + +std::string +ContinueExpr::as_string () const +{ + std::string str ("continue "); + + if (has_label ()) + { + str += label.as_string (); + } + + return str; +} + +std::string +NegationExpr::as_string () const +{ + std::string str; + + switch (negation_type) + { + case NEGATE: + str = "-"; + break; + case NOT: + str = "!"; + break; + default: + return "ERROR_MARK_STRING - negation expr"; + } + + str += main_or_left_expr->as_string (); + + return str; +} + +std::string +RangeFromExpr::as_string () const +{ + return from->as_string () + ".."; +} + +std::string +RangeFullExpr::as_string () const +{ + return ".."; +} + +std::string +ArrayIndexExpr::as_string () const +{ + return array_expr->as_string () + "[" + index_expr->as_string () + "]"; +} + +std::string +AssignmentExpr::as_string () const +{ + return main_or_left_expr->as_string () + " = " + right_expr->as_string () + + "::" + get_mappings ().as_string (); +} + +std::string +AsyncBlockExpr::as_string () const +{ + std::string str = "AsyncBlockExpr: "; + + // get outer attributes + str += "\n " + Expr::as_string (); + + str += "\n Has move: "; + str += has_move ? "true" : "false"; + + return str + "\n" + block_expr->as_string (); +} + +std::string +ComparisonExpr::as_string () const +{ + std::string str (main_or_left_expr->as_string ()); + + switch (expr_type) + { + case EQUAL: + str += " == "; + break; + case NOT_EQUAL: + str += " != "; + break; + case GREATER_THAN: + str += " > "; + break; + case LESS_THAN: + str += " < "; + break; + case GREATER_OR_EQUAL: + str += " >= "; + break; + case LESS_OR_EQUAL: + str += " <= "; + break; + default: + return "ERROR_MARK_STRING - comparison expr"; + } + + str += right_expr->as_string (); + + return str; +} + +std::string +MethodCallExpr::as_string () const +{ + std::string str ("MethodCallExpr: \n Object (receiver) expr: "); + + str += receiver->as_string (); + + str += "\n Method path segment: \n"; + + str += method_name.as_string (); + + str += "\n Call params:"; + if (params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : params) + { + if (param == nullptr) + { + return "ERROR_MARK_STRING - method call expr param is null"; + } + + str += "\n " + param->as_string (); + } + } + + return str; +} + +std::string +TupleIndexExpr::as_string () const +{ + return tuple_expr->as_string () + "." + std::to_string (tuple_index); +} + +std::string +DereferenceExpr::as_string () const +{ + return "*" + main_or_left_expr->as_string (); +} + +std::string +FieldAccessExpr::as_string () const +{ + return receiver->as_string () + "." + field; +} + +std::string +LazyBooleanExpr::as_string () const +{ + std::string str (main_or_left_expr->as_string ()); + + switch (expr_type) + { + case LOGICAL_OR: + str += " || "; + break; + case LOGICAL_AND: + str += " && "; + break; + default: + return "ERROR_MARK_STRING - lazy boolean expr out of bounds"; + } + + str += right_expr->as_string (); + + return str; +} + +std::string +RangeFromToExpr::as_string () const +{ + return from->as_string () + ".." + to->as_string (); +} + +std::string +RangeToInclExpr::as_string () const +{ + return "..=" + to->as_string (); +} + +std::string +UnsafeBlockExpr::as_string () const +{ + std::string istr = indent_spaces (enter); + std::string str = istr + "UnsafeBlockExpr:"; + str += istr + "{"; + + // get outer attributes + str += "\n" + indent_spaces (stay) + Expr::as_string (); + + return str + "\n" + indent_spaces (out) + "}\n" + expr->as_string (); +} + +std::string +ClosureExprInner::as_string () const +{ + std::string str = ClosureExpr::as_string (); + + str += "\n Expression: " + closure_inner->as_string (); + + return str; +} + +std::string +IfExpr::as_string () const +{ + std::string str ("IfExpr: "); + + str += "\n Condition expr: " + condition->as_string (); + + str += "\n If block expr: " + if_block->as_string (); + + return str; +} + +std::string +IfExprConseqElse::as_string () const +{ + std::string str = IfExpr::as_string (); + + str += "\n Else block expr: " + else_block->as_string (); + + return str; +} + +std::string +IfExprConseqIf::as_string () const +{ + std::string str = IfExpr::as_string (); + + str += "\n Else if expr: \n " + conseq_if_expr->as_string (); + + return str; +} + +std::string +IfExprConseqIfLet::as_string () const +{ + std::string str = IfExpr::as_string (); + + str += "\n Else if let expr: \n " + if_let_expr->as_string (); + + return str; +} + +std::string +IfLetExpr::as_string () const +{ + std::string str ("IfLetExpr: "); + + str += "\n Condition match arm patterns: "; + if (match_arm_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &pattern : match_arm_patterns) + { + str += "\n " + pattern->as_string (); + } + } + + str += "\n Scrutinee expr: " + value->as_string (); + + str += "\n If let block expr: " + if_block->as_string (); + + return str; +} + +std::string +IfLetExprConseqElse::as_string () const +{ + std::string str = IfLetExpr::as_string (); + + str += "\n Else block expr: " + else_block->as_string (); + + return str; +} + +std::string +IfLetExprConseqIf::as_string () const +{ + std::string str = IfLetExpr::as_string (); + + str += "\n Else if expr: \n " + if_expr->as_string (); + + return str; +} + +std::string +IfLetExprConseqIfLet::as_string () const +{ + std::string str = IfLetExpr::as_string (); + + str += "\n Else if let expr: \n " + if_let_expr->as_string (); + + return str; +} + +std::string +RangeFromToInclExpr::as_string () const +{ + return from->as_string () + "..=" + to->as_string (); +} + +std::string +ErrorPropagationExpr::as_string () const +{ + return main_or_left_expr->as_string () + "?"; +} + +std::string +CompoundAssignmentExpr::as_string () const +{ + std::string operator_str; + operator_str.reserve (1); + + // get operator string + switch (expr_type) + { + case ADD: + operator_str = "+"; + break; + case SUBTRACT: + operator_str = "-"; + break; + case MULTIPLY: + operator_str = "*"; + break; + case DIVIDE: + operator_str = "/"; + break; + case MODULUS: + operator_str = "%"; + break; + case BITWISE_AND: + operator_str = "&"; + break; + case BITWISE_OR: + operator_str = "|"; + break; + case BITWISE_XOR: + operator_str = "^"; + break; + case LEFT_SHIFT: + operator_str = "<<"; + break; + case RIGHT_SHIFT: + operator_str = ">>"; + break; + default: + operator_str = "invalid operator. wtf"; + break; + } + + operator_str += "="; + + std::string str ("CompoundAssignmentExpr: "); + if (main_or_left_expr == nullptr || right_expr == nullptr) + { + str += "error. this is probably a parsing failure."; + } + else + { + str += "\n left: " + main_or_left_expr->as_string (); + str += "\n right: " + right_expr->as_string (); + str += "\n operator: " + operator_str; + } + + return str; +} + +std::string +ArithmeticOrLogicalExpr::as_string () const +{ + std::string operator_str; + operator_str.reserve (1); + + // get operator string + switch (expr_type) + { + case ADD: + operator_str = "+"; + break; + case SUBTRACT: + operator_str = "-"; + break; + case MULTIPLY: + operator_str = "*"; + break; + case DIVIDE: + operator_str = "/"; + break; + case MODULUS: + operator_str = "%"; + break; + case BITWISE_AND: + operator_str = "&"; + break; + case BITWISE_OR: + operator_str = "|"; + break; + case BITWISE_XOR: + operator_str = "^"; + break; + case LEFT_SHIFT: + operator_str = "<<"; + break; + case RIGHT_SHIFT: + operator_str = ">>"; + break; + default: + operator_str = "invalid operator. wtf"; + break; + } + + std::string str ("ArithmeticOrLogicalExpr: "); + if (main_or_left_expr == nullptr || right_expr == nullptr) + { + str += "error. this is probably a parsing failure."; + } + else + { + str += main_or_left_expr->as_string () + " "; + str += operator_str + " "; + str += right_expr->as_string (); + } + + return str + "::" + get_mappings ().as_string (); +} + +std::string +CallExpr::as_string () const +{ + std::string str = function->as_string () + "("; + if (!has_params ()) + str += "none"; + else + { + for (const auto ¶m : params) + { + if (param == nullptr) + { + return "ERROR_MARK_STRING - call expr param is null"; + } + + str += param->as_string () + ","; + } + } + return str + ")" + "::" + get_mappings ().as_string (); +} + +std::string +WhileLoopExpr::as_string () const +{ + std::string str ("WhileLoopExpr: "); + + str += "\n Label: "; + if (!has_loop_label ()) + { + str += "none"; + } + else + { + str += loop_label.as_string (); + } + + str += "\n Conditional expr: " + condition->as_string (); + + str += "\n Loop block: " + loop_block->as_string (); + + return str; +} + +std::string +WhileLetLoopExpr::as_string () const +{ + std::string str ("WhileLetLoopExpr: "); + + str += "\n Label: "; + if (!has_loop_label ()) + { + str += "none"; + } + else + { + str += loop_label.as_string (); + } + + str += "\n Match arm patterns: "; + if (match_arm_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &pattern : match_arm_patterns) + { + str += "\n " + pattern->as_string (); + } + } + + str += "\n Scrutinee expr: " + condition->as_string (); + + str += "\n Loop block: " + loop_block->as_string (); + + return str; +} + +std::string +LoopExpr::as_string () const +{ + std::string str ("LoopExpr: (infinite loop)"); + + str += "\n Label: "; + if (!has_loop_label ()) + { + str += "none"; + } + else + { + str += loop_label.as_string (); + } + + str += "\n Loop block: " + loop_block->as_string (); + + return str; +} + +std::string +ArrayExpr::as_string () const +{ + std::string str ("ArrayExpr:"); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n Array elems: "; + if (!has_array_elems ()) + { + str += "none"; + } + else + { + str += internal_elements->as_string (); + } + + return str; +} + +std::string +AwaitExpr::as_string () const +{ + return awaited_expr->as_string () + ".await"; +} + +std::string +BreakExpr::as_string () const +{ + std::string str ("break "); + + if (has_label ()) + { + str += label.as_string () + " "; + } + + if (has_break_expr ()) + { + str += break_expr->as_string (); + } + + return str; +} + +std::string +LoopLabel::as_string () const +{ + return label.as_string () + ": (label) "; +} + +std::string +MatchArm::as_string () const +{ + // outer attributes + std::string str = "Outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\nPatterns: "; + if (match_arm_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &pattern : match_arm_patterns) + { + str += "\n " + pattern->as_string (); + } + } + + str += "\nGuard expr: "; + if (!has_match_arm_guard ()) + { + str += "none"; + } + else + { + str += guard_expr->as_string (); + } + + return str; +} + +std::string +MatchCase::as_string () const +{ + std::string str ("MatchCase: (match arm) "); + + str += "\n Match arm matcher: \n" + arm.as_string (); + str += "\n Expr: " + expr->as_string (); + + return str; +} + +/*std::string +MatchCaseBlockExpr::as_string () const +{ + std::string str = MatchCase::as_string (); + + str += "\n Block expr: " + block_expr->as_string (); + + return str; +} + +std::string +MatchCaseExpr::as_string () const +{ + std::string str = MatchCase::as_string (); + + str += "\n Expr: " + expr->as_string (); + + return str; +}*/ + +std::string +MatchExpr::as_string () const +{ + std::string str ("MatchExpr:"); + + str += "\n Scrutinee expr: " + branch_value->as_string (); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // match arms + str += "\n Match arms: "; + if (match_arms.empty ()) + { + str += "none"; + } + else + { + for (const auto &arm : match_arms) + str += "\n " + arm.as_string (); + } + + return str; +} + +std::string +TupleExpr::as_string () const +{ + std::string str ("TupleExpr:"); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n Tuple elements: "; + if (tuple_elems.empty ()) + { + str += "none"; + } + else + { + for (const auto &elem : tuple_elems) + { + str += "\n " + elem->as_string (); + } + } + + return str; +} + +std::string +ExprStmtWithoutBlock::as_string () const +{ + std::string str ("ExprStmtWithoutBlock:\n"); + indent_spaces (enter); + str += indent_spaces (stay); + + if (expr == nullptr) + { + str += "none (this shouldn't happen and is probably an error)"; + } + else + { + str += expr->as_string (); + } + indent_spaces (out); + + return str; +} + +std::string +FunctionParam::as_string () const +{ + return param_name->as_string () + " : " + type->as_string (); +} + +std::string +FunctionQualifiers::as_string () const +{ + std::string str; + + switch (const_status) + { + case NONE: + // do nothing + break; + case CONST: + str += "const "; + break; + case ASYNC: + str += "async "; + break; + default: + return "ERROR_MARK_STRING: async-const status failure"; + } + + if (has_unsafe) + { + str += "unsafe "; + } + + if (has_extern) + { + str += "extern"; + if (extern_abi != "") + { + str += " \"" + extern_abi + "\""; + } + } + + return str; +} + +std::string +TraitBound::as_string () const +{ + std::string str ("TraitBound:"); + + str += "\n Has opening question mark: "; + if (opening_question_mark) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n For lifetimes: "; + if (!has_for_lifetimes ()) + { + str += "none"; + } + else + { + for (const auto &lifetime : for_lifetimes) + { + str += "\n " + lifetime.as_string (); + } + } + + str += "\n Type path: " + type_path.as_string (); + + return str; +} + +std::string +MacroMatcher::as_string () const +{ + std::string str ("Macro matcher: "); + + str += "\n Delim type: "; + + switch (delim_type) + { + case PARENS: + str += "parentheses"; + break; + case SQUARE: + str += "square"; + break; + case CURLY: + str += "curly"; + break; + default: + return "ERROR_MARK_STRING - macro matcher delim"; + } + + str += "\n Matches: "; + + if (matches.empty ()) + { + str += "none"; + } + else + { + for (const auto &match : matches) + { + str += "\n " + match->as_string (); + } + } + + return str; +} + +std::string +LifetimeParam::as_string () const +{ + std::string str ("LifetimeParam: "); + + str += "\n Outer attribute: "; + if (!has_outer_attribute ()) + { + str += "none"; + } + else + { + str += outer_attr.as_string (); + } + + str += "\n Lifetime: " + lifetime.as_string (); + + str += "\n Lifetime bounds: "; + if (!has_lifetime_bounds ()) + { + str += "none"; + } + else + { + for (const auto &bound : lifetime_bounds) + { + str += "\n " + bound.as_string (); + } + } + + return str; +} + +std::string +MacroMatchFragment::as_string () const +{ + return "$" + ident + ": " + frag_spec_to_str (frag_spec); +} + +std::string +QualifiedPathInType::as_string () const +{ + std::string str = path_type.as_string (); + + for (const auto &segment : segments) + { + str += "::" + segment->as_string (); + } + + return str; +} + +std::string +MacroMatchRepetition::as_string () const +{ + std::string str ("Macro match repetition: "); + + str += "\n Matches: "; + if (matches.empty ()) + { + str += "none"; + } + else + { + for (const auto &match : matches) + { + str += "\n " + match->as_string (); + } + } + + str += "\n Sep: "; + if (!has_sep ()) + { + str += "none"; + } + else + { + str += sep->as_string (); + } + + str += "\n Op: "; + switch (op) + { + case ASTERISK: + str += "*"; + break; + case PLUS: + str += "+"; + break; + case QUESTION_MARK: + str += "?"; + break; + case NONE: + str += "no op? shouldn't be allowed"; + break; + default: + return "ERROR_MARK_STRING - unknown op in macro match repetition"; + } + + return str; +} + +std::string +Lifetime::as_string () const +{ + if (is_error ()) + { + return "error lifetime"; + } + + switch (lifetime_type) + { + case NAMED: + return "'" + lifetime_name; + case STATIC: + return "'static"; + case WILDCARD: + return "'_"; + default: + return "ERROR-MARK-STRING: lifetime type failure"; + } +} + +std::string +TypePath::as_string () const +{ + std::string str; + + if (has_opening_scope_resolution) + { + str = "::"; + } + + for (const auto &segment : segments) + { + str += segment->as_string () + "::"; + } + + // kinda hack - remove last 2 '::' characters + str.erase (str.length () - 2); + + return str; +} + +std::string +TypeParam::as_string () const +{ + std::string str ("TypeParam: "); + + str += "\n Outer attribute: "; + if (!has_outer_attribute ()) + { + str += "none"; + } + else + { + str += outer_attr.as_string (); + } + + str += "\n Identifier: " + type_representation; + + str += "\n Type param bounds: "; + if (!has_type_param_bounds ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + str += "\n " + bound->as_string (); + } + } + + str += "\n Type: "; + if (!has_type ()) + { + str += "none"; + } + else + { + str += type->as_string (); + } + + return str; +} + +SimplePath +PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const +{ + if (!has_segments ()) + { + return SimplePath::create_empty (); + } + + // create vector of reserved size (to minimise reallocations) + std::vector<SimplePathSegment> simple_segments; + simple_segments.reserve (segments.size ()); + + for (const auto &segment : segments) + { + // return empty path if doesn't meet simple path segment requirements + if (segment.is_error () || segment.has_generic_args () + || segment.as_string () == "Self") + { + return SimplePath::create_empty (); + } + + // create segment and add to vector + std::string segment_str = segment.as_string (); + simple_segments.push_back ( + SimplePathSegment (std::move (segment_str), segment.get_locus ())); + } + + // kind of a HACK to get locus depending on opening scope resolution + Location locus = Linemap::unknown_location (); + if (with_opening_scope_resolution) + { + locus = simple_segments[0].get_locus () - 2; // minus 2 chars for :: + } + else + { + locus = simple_segments[0].get_locus (); + } + + return SimplePath (std::move (simple_segments), with_opening_scope_resolution, + locus); +} + +SimplePath +TypePath::as_simple_path () const +{ + if (segments.empty ()) + { + return SimplePath::create_empty (); + } + + // create vector of reserved size (to minimise reallocations) + std::vector<SimplePathSegment> simple_segments; + simple_segments.reserve (segments.size ()); + + for (const auto &segment : segments) + { + // return empty path if doesn't meet simple path segment requirements + if (segment == nullptr || segment->is_error () + || !segment->is_ident_only () || segment->as_string () == "Self") + { + return SimplePath::create_empty (); + } + + // create segment and add to vector + std::string segment_str = segment->as_string (); + simple_segments.push_back ( + SimplePathSegment (std::move (segment_str), segment->get_locus ())); + } + + return SimplePath (std::move (simple_segments), has_opening_scope_resolution, + locus); +} + +std::string +PathExprSegment::as_string () const +{ + std::string ident_str = segment_name.as_string (); + if (has_generic_args ()) + { + ident_str += "::<" + generic_args.as_string () + ">"; + } + + return ident_str; +} + +std::string +GenericArgs::as_string () const +{ + std::string args; + + // lifetime args + if (!lifetime_args.empty ()) + { + auto i = lifetime_args.begin (); + auto e = lifetime_args.end (); + + for (; i != e; i++) + { + args += (*i).as_string (); + if (e != i + 1) + args += ", "; + } + } + + // type args + if (!type_args.empty ()) + { + auto i = type_args.begin (); + auto e = type_args.end (); + + for (; i != e; i++) + { + args += (*i)->as_string (); + if (e != i + 1) + args += ", "; + } + } + + // binding args + if (!binding_args.empty ()) + { + auto i = binding_args.begin (); + auto e = binding_args.end (); + + for (; i != e; i++) + { + args += (*i).as_string (); + if (e != i + 1) + args += ", "; + } + } + + return args; +} + +std::string +GenericArgsBinding::as_string () const +{ + return identifier + " = " + type->as_string (); +} + +std::string +ForLoopExpr::as_string () const +{ + std::string str ("ForLoopExpr: "); + + str += "\n Label: "; + if (!has_loop_label ()) + { + str += "none"; + } + else + { + str += loop_label.as_string (); + } + + str += "\n Pattern: " + pattern->as_string (); + + str += "\n Iterator expr: " + iterator_expr->as_string (); + + str += "\n Loop block: " + loop_block->as_string (); + + return str; +} + +std::string +RangePattern::as_string () const +{ + if (has_ellipsis_syntax) + { + return lower->as_string () + "..." + upper->as_string (); + } + else + { + return lower->as_string () + "..=" + upper->as_string (); + } +} + +std::string +RangePatternBoundLiteral::as_string () const +{ + std::string str; + + if (has_minus) + { + str += "-"; + } + + str += literal.as_string (); + + return str; +} + +std::string +SlicePattern::as_string () const +{ + std::string str ("SlicePattern: "); + + for (const auto &pattern : items) + { + str += "\n " + pattern->as_string (); + } + + return str; +} + +std::string +TuplePatternItemsMultiple::as_string () const +{ + std::string str; + + for (const auto &pattern : patterns) + { + str += "\n " + pattern->as_string (); + } + + return str; +} + +std::string +TuplePatternItemsRanged::as_string () const +{ + std::string str; + + str += "\n Lower patterns: "; + if (lower_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &lower : lower_patterns) + { + str += "\n " + lower->as_string (); + } + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &upper : upper_patterns) + { + str += "\n " + upper->as_string (); + } + } + + return str; +} + +std::string +TuplePattern::as_string () const +{ + return "TuplePattern: " + items->as_string (); +} + +std::string +StructPatternField::as_string () const +{ + // outer attributes + std::string str ("Outer attributes: "); + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + return str; +} + +std::string +StructPatternFieldIdent::as_string () const +{ + std::string str = StructPatternField::as_string (); + + str += "\n"; + + if (has_ref) + { + str += "ref "; + } + + if (has_mut) + { + str += "mut "; + } + + str += ident; + + return str; +} + +std::string +StructPatternFieldTuplePat::as_string () const +{ + std::string str = StructPatternField::as_string (); + + str += "\n"; + + str += std::to_string (index) + " : " + tuple_pattern->as_string (); + + return str; +} + +std::string +StructPatternFieldIdentPat::as_string () const +{ + std::string str = StructPatternField::as_string (); + + str += "\n"; + + str += ident + " : " + ident_pattern->as_string (); + + return str; +} + +std::string +StructPatternElements::as_string () const +{ + std::string str ("\n Fields: "); + + if (!has_struct_pattern_fields ()) + { + str += "none"; + } + else + { + for (const auto &field : fields) + { + str += "\n " + field->as_string (); + } + } + + str += "\n Etc: "; + if (has_struct_pattern_etc) + { + str += "true"; + } + else + { + str += "false"; + } + + return str; +} + +std::string +StructPattern::as_string () const +{ + std::string str ("StructPattern: \n Path: "); + + str += path.as_string (); + + str += "\n Struct pattern elems: "; + if (!has_struct_pattern_elems ()) + { + str += "none"; + } + else + { + str += elems.as_string (); + } + + return str; +} + +std::string +LiteralPattern::as_string () const +{ + std::string str; + + if (has_minus) + { + str += "-"; + } + + return str + lit.as_string (); +} + +std::string +ReferencePattern::as_string () const +{ + std::string str ("&"); + + if (has_two_amps) + { + str += "&"; + } + + if (is_mut) + { + str += "mut "; + } + + str += pattern->as_string (); + + return str; +} + +std::string +IdentifierPattern::as_string () const +{ + std::string str; + + if (is_ref) + { + str += "ref "; + } + + if (is_mut) + { + str += "mut "; + } + + str += variable_ident; + + if (has_pattern_to_bind ()) + { + str += " @ " + to_bind->as_string (); + } + + return str; +} + +std::string +TupleStructItemsNoRange::as_string () const +{ + std::string str; + + for (const auto &pattern : patterns) + { + str += "\n " + pattern->as_string (); + } + + return str; +} + +std::string +TupleStructItemsRange::as_string () const +{ + std::string str ("\n Lower patterns: "); + + if (lower_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &lower : lower_patterns) + { + str += "\n " + lower->as_string (); + } + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &upper : upper_patterns) + { + str += "\n " + upper->as_string (); + } + } + + return str; +} + +std::string +TupleStructPattern::as_string () const +{ + std::string str ("TupleStructPattern: \n Path: "); + + str += path.as_string (); + + str += "\n Tuple struct items: " + items->as_string (); + + return str; +} + +std::string +LetStmt::as_string () const +{ + // outer attributes + std::string str = "Outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + indent_spaces (enter); + for (const auto &attr : outer_attrs) + { + str += "\n" + indent_spaces (stay) + attr.as_string (); + } + indent_spaces (out); + } + + str += "\n" + indent_spaces (stay) + "let " + variables_pattern->as_string (); + + if (has_type ()) + { + str += " : " + type->as_string (); + } + + if (has_init_expr ()) + { + str += " = " + init_expr->as_string (); + } + + return str; +} + +// Used to get outer attributes for expressions. +std::string +Expr::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + return str; +} + +// hopefully definition here will prevent circular dependency issue +TraitBound * +TypePath::to_trait_bound (bool in_parens) const +{ + // create clone FIXME is this required? or is copy constructor automatically + // called? + TypePath copy (*this); + return new TraitBound (std::move (copy), copy.get_locus (), in_parens); +} + +std::string +InferredType::as_string () const +{ + return "_ (inferred)"; +} + +std::string +TypeCastExpr::as_string () const +{ + return main_or_left_expr->as_string () + " as " + + type_to_convert_to->as_string (); +} + +std::string +ImplTraitType::as_string () const +{ + std::string str ("ImplTraitType: \n TypeParamBounds: "); + + if (type_param_bounds.empty ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + str += "\n " + bound->as_string (); + } + } + + return str; +} + +std::string +ReferenceType::as_string () const +{ + std::string str ("&"); + + if (has_lifetime ()) + { + str += lifetime.as_string () + " "; + } + + if (has_mut) + { + str += "mut "; + } + + str += type->as_string (); + + return str; +} + +std::string +RawPointerType::as_string () const +{ + std::string str ("*"); + + switch (pointer_type) + { + case MUT: + str += "mut "; + break; + case CONST: + str += "const "; + break; + default: + return "ERROR_MARK_STRING - unknown pointer type in raw pointer type"; + } + + str += type->as_string (); + + return str; +} + +std::string +TraitObjectType::as_string () const +{ + std::string str ("TraitObjectType: \n Has dyn dispatch: "); + + if (has_dyn) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n TypeParamBounds: "; + if (type_param_bounds.empty ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + str += "\n " + bound->as_string (); + } + } + + return str; +} + +std::string +BareFunctionType::as_string () const +{ + std::string str ("BareFunctionType: \n For lifetimes: "); + + if (!has_for_lifetimes ()) + { + str += "none"; + } + else + { + for (const auto &for_lifetime : for_lifetimes) + { + str += "\n " + for_lifetime.as_string (); + } + } + + str += "\n Qualifiers: " + function_qualifiers.as_string (); + + str += "\n Params: "; + if (params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : params) + { + str += "\n " + param.as_string (); + } + } + + str += "\n Is variadic: "; + if (is_variadic) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n Return type: "; + if (!has_return_type ()) + { + str += "none (void)"; + } + else + { + str += return_type->as_string (); + } + + return str; +} + +std::string +ImplTraitTypeOneBound::as_string () const +{ + std::string str ("ImplTraitTypeOneBound: \n TraitBound: "); + + return str + trait_bound.as_string (); +} + +std::string +TypePathSegmentGeneric::as_string () const +{ + return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">"; +} + +std::string +TraitObjectTypeOneBound::as_string () const +{ + std::string str ("TraitObjectTypeOneBound: \n Has dyn dispatch: "); + + if (has_dyn) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n TraitBound: " + trait_bound.as_string (); + + return str; +} + +std::string +TypePathFunction::as_string () const +{ + std::string str ("("); + + if (has_inputs ()) + { + auto i = inputs.begin (); + auto e = inputs.end (); + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + } + + str += ")"; + + if (has_return_type ()) + { + str += " -> " + return_type->as_string (); + } + + return str; +} + +std::string +TypePathSegmentFunction::as_string () const +{ + return TypePathSegment::as_string () + function_path.as_string (); +} + +std::string +ArrayType::as_string () const +{ + return "[" + elem_type->as_string () + "; " + size->as_string () + "]"; +} + +std::string +SliceType::as_string () const +{ + return "[" + elem_type->as_string () + "]"; +} + +std::string +TupleType::as_string () const +{ + std::string str ("("); + + if (!is_unit_type ()) + { + auto i = elems.begin (); + auto e = elems.end (); + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + } + + str += ")"; + + return str; +} + +std::string +StructExpr::as_string () const +{ + std::string str = ExprWithoutBlock::as_string (); + indent_spaces (enter); + str += "\n" + indent_spaces (stay) + "StructExpr:"; + indent_spaces (enter); + str += "\n" + indent_spaces (stay) + "PathInExpr:\n"; + str += indent_spaces (stay) + struct_name.as_string (); + indent_spaces (out); + indent_spaces (out); + return str; +} + +std::string +StructExprTuple::as_string () const +{ + std::string str = StructExpr::as_string (); + + if (exprs.empty ()) + { + str += "()"; + } + else + { + auto i = exprs.begin (); + auto e = exprs.end (); + + // debug - null pointer check + if (*i == nullptr) + { + return "ERROR_MARK_STRING - nullptr struct expr tuple field"; + } + + str += '('; + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + str += ')'; + } + + indent_spaces (enter); + indent_spaces (enter); + // inner attributes + str += "\n" + indent_spaces (stay) + "inner attributes:"; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n" + indent_spaces (stay) + attr.as_string (); + } + } + indent_spaces (out); + indent_spaces (out); + + return str; +} + +std::string +StructExprStruct::as_string () const +{ + std::string str ("StructExprStruct (or subclass): "); + + str += "\n Path: " + get_struct_name ().as_string (); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + return str; +} + +std::string +StructBase::as_string () const +{ + if (base_struct != nullptr) + { + return base_struct->as_string (); + } + else + { + return "ERROR_MARK_STRING - invalid struct base had as string applied"; + } +} + +std::string +StructExprFieldWithVal::as_string () const +{ + // used to get value string + return value->as_string (); +} + +std::string +StructExprFieldIdentifierValue::as_string () const +{ + return field_name + " : " + StructExprFieldWithVal::as_string (); +} + +std::string +StructExprFieldIndexValue::as_string () const +{ + return std::to_string (index) + " : " + StructExprFieldWithVal::as_string (); +} + +std::string +StructExprStructFields::as_string () const +{ + std::string str = StructExprStruct::as_string (); + + str += "\n Fields: "; + if (fields.empty ()) + { + str += "none"; + } + else + { + for (const auto &field : fields) + { + str += "\n " + field->as_string (); + } + } + + str += "\n Struct base: "; + if (!has_struct_base ()) + { + str += "none"; + } + else + { + str += struct_base.as_string (); + } + + return str; +} + +std::string +EnumItem::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n" + variant_name; + + return str; +} + +std::string +EnumItemTuple::as_string () const +{ + std::string str = EnumItem::as_string (); + + // add tuple opening parens + str += "("; + + // tuple fields + if (has_tuple_fields ()) + { + auto i = tuple_fields.begin (); + auto e = tuple_fields.end (); + + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + } + + // add tuple closing parens + str += ")"; + + return str; +} + +std::string +TupleField::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + if (has_visibility ()) + { + str += "\n" + visibility.as_string (); + } + + str += " " + field_type->as_string (); + + return str; +} + +std::string +EnumItemStruct::as_string () const +{ + std::string str = EnumItem::as_string (); + + // add struct opening parens + str += "{"; + + // tuple fields + if (has_struct_fields ()) + { + auto i = struct_fields.begin (); + auto e = struct_fields.end (); + + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + } + + // add struct closing parens + str += "}"; + + return str; +} + +std::string +StructField::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + if (has_visibility ()) + { + str += "\n" + visibility.as_string (); + } + + str += " " + field_name + " : " + field_type->as_string (); + + return str; +} + +std::string +EnumItemDiscriminant::as_string () const +{ + std::string str = EnumItem::as_string (); + + // add equal and expression + str += " = " + expression->as_string (); + + return str; +} + +std::string +ExternalItem::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // start visibility on new line and with a space + str += "\n" + visibility.as_string () + " "; + + return str; +} + +std::string +ExternalStaticItem::as_string () const +{ + std::string str = ExternalItem::as_string (); + + str += "static "; + + if (has_mut) + { + str += "mut "; + } + + // add name + str += get_item_name (); + + // add type on new line + str += "\n Type: " + item_type->as_string (); + + return str; +} + +std::string +ExternalFunctionItem::as_string () const +{ + std::string str = ExternalItem::as_string (); + + str += "fn "; + + // add name + str += get_item_name (); + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in external function item."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + // function params + str += "\n Function params: "; + if (function_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : function_params) + { + str += "\n " + param.as_string (); + } + if (has_variadics) + { + str += "\n .. (variadic)"; + } + } + + // add type on new line + str += "\n (return) Type: " + return_type->as_string (); + + // where clause + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +NamedFunctionParam::as_string () const +{ + std::string str = name; + + str += "\n Type: " + param_type->as_string (); + + return str; +} + +/*std::string TraitItem::as_string() const { + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - +just the body for (const auto& attr : outer_attrs) { str += "\n " + +attr.as_string(); + } + } + + return str; +}*/ + +std::string +TraitItemFunc::as_string () const +{ + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n" + decl.as_string (); + + str += "\n Definition (block expr): "; + if (has_definition ()) + { + str += block_expr->as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +TraitFunctionDecl::as_string () const +{ + std::string str = qualifiers.as_string () + "fn " + function_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in trait function decl."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Function params: "; + if (has_params ()) + { + for (const auto ¶m : function_params) + { + str += "\n " + param.as_string (); + } + } + else + { + str += "none"; + } + + str += "\n Return type: "; + if (has_return_type ()) + { + str += return_type->as_string (); + } + else + { + str += "none (void)"; + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +TraitItemMethod::as_string () const +{ + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n" + decl.as_string (); + + str += "\n Definition (block expr): "; + if (has_definition ()) + { + str += block_expr->as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +TraitMethodDecl::as_string () const +{ + std::string str = qualifiers.as_string () + "fn " + function_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in trait function decl."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Self param: " + self_param.as_string (); + + str += "\n Function params: "; + if (has_params ()) + { + for (const auto ¶m : function_params) + { + str += "\n " + param.as_string (); + } + } + else + { + str += "none"; + } + + str += "\n Return type: "; + if (has_return_type ()) + { + str += return_type->as_string (); + } + else + { + str += "none (void)"; + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +TraitItemConst::as_string () const +{ + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\nconst " + name + " : " + type->as_string (); + + if (has_expression ()) + { + str += " = " + expr->as_string (); + } + + return str; +} + +std::string +TraitItemType::as_string () const +{ + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\ntype " + name; + + str += "\n Type param bounds: "; + if (!has_type_param_bounds ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + // DEBUG: null pointer check + if (bound == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "type param bound in trait item type."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + bound->as_string (); + } + } + + return str; +} + +std::string +SelfParam::as_string () const +{ + if (is_error ()) + { + return "error"; + } + else + { + if (has_type ()) + { + // type (i.e. not ref, no lifetime) + std::string str; + + if (is_mut) + { + str += "mut "; + } + + str += "self : "; + + str += type->as_string (); + + return str; + } + else if (has_lifetime ()) + { + // ref and lifetime + std::string str = "&" + lifetime.as_string () + " "; + + if (is_mut) + { + str += "mut "; + } + + str += "self"; + + return str; + } + else if (has_ref) + { + // ref with no lifetime + std::string str = "&"; + + if (is_mut) + { + str += " mut "; + } + + str += "self"; + + return str; + } + else + { + // no ref, no type + std::string str; + + if (is_mut) + { + str += "mut "; + } + + str += "self"; + + return str; + } + } +} + +std::string +ArrayElemsCopied::as_string () const +{ + return elem_to_copy->as_string () + "; " + num_copies->as_string (); +} + +std::string +LifetimeWhereClauseItem::as_string () const +{ + std::string str ("Lifetime: "); + + str += lifetime.as_string (); + + str += "\nLifetime bounds: "; + + for (const auto &bound : lifetime_bounds) + { + str += "\n " + bound.as_string (); + } + + return str; +} + +std::string +TypeBoundWhereClauseItem::as_string () const +{ + std::string str ("For lifetimes: "); + + if (!has_for_lifetimes ()) + { + str += "none"; + } + else + { + for (const auto &for_lifetime : for_lifetimes) + { + str += "\n " + for_lifetime.as_string (); + } + } + + str += "\nType: " + bound_type->as_string (); + + str += "\nType param bounds bounds: "; + + for (const auto &bound : type_param_bounds) + { + // debug null pointer check + if (bound == nullptr) + { + return "nullptr_POINTER_MARK - type param bounds"; + } + + str += "\n " + bound->as_string (); + } + + return str; +} + +std::string +ArrayElemsValues::as_string () const +{ + std::string str; + + for (const auto &expr : values) + { + // DEBUG: null pointer check + if (expr == nullptr) + { + fprintf (stderr, + "something really terrible has gone wrong - null pointer " + "expr in array elems values."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + expr->as_string (); + } + + return str; +} + +std::string +MaybeNamedParam::as_string () const +{ + std::string str; + + switch (param_kind) + { + case UNNAMED: + break; + case IDENTIFIER: + str = name + " : "; + break; + case WILDCARD: + str = "_ : "; + break; + default: + return "ERROR_MARK_STRING - maybe named param unrecognised param kind"; + } + + str += param_type->as_string (); + + return str; +} + +std::string +MetaItemSeq::as_string () const +{ + std::string path_str = path.as_string () + "("; + + auto i = seq.begin (); + auto e = seq.end (); + + for (; i != e; i++) + { + path_str += (*i)->as_string (); + if (e != i + 1) + path_str += ", "; + } + + return path_str + ")"; +} + +std::string +MetaListPaths::as_string () const +{ + std::string str = ident + "("; + + auto i = paths.begin (); + auto e = paths.end (); + + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + + return str + ")"; +} + +std::string +MetaListNameValueStr::as_string () const +{ + std::string str = ident + "("; + + auto i = strs.begin (); + auto e = strs.end (); + + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + + return str + ")"; +} + +std::string +AttrInputMetaItemContainer::as_string () const +{ + std::string str = "("; + + auto i = items.begin (); + auto e = items.end (); + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + + return str + ")"; +} + +/* Override that calls the function recursively on all items contained within + * the module. */ +void +ModuleBodied::add_crate_name (std::vector<std::string> &names) const +{ + /* TODO: test whether module has been 'cfg'-ed out to determine whether to + * exclude it from search */ + + for (const auto &item : items) + item->add_crate_name (names); +} + +void +Attribute::parse_attr_to_meta_item () +{ + // only parse if has attribute input + if (!has_attr_input ()) + return; + + std::unique_ptr<AttrInput> converted_input ( + attr_input->parse_to_meta_item ()); + + if (converted_input != nullptr) + attr_input = std::move (converted_input); +} + +AttrInput * +DelimTokenTree::parse_to_meta_item () const +{ + // must have token trees + if (token_trees.empty ()) + return nullptr; + + /* assume top-level delim token tree in attribute - convert all nested ones + * to token stream */ + std::vector<std::unique_ptr<Token> > token_stream = to_token_stream (); + + MacroParser parser (std::move (token_stream)); + std::vector<std::unique_ptr<MetaItemInner> > meta_items ( + parser.parse_meta_item_seq ()); + + return new AttrInputMetaItemContainer (std::move (meta_items)); +} + +std::unique_ptr<MetaItemInner> +MacroParser::parse_meta_item_inner () +{ + // if first tok not identifier, not a "special" case one + if (peek_token ()->get_id () != IDENTIFIER) + { + switch (peek_token ()->get_id ()) + { + case CHAR_LITERAL: + case STRING_LITERAL: + case BYTE_CHAR_LITERAL: + case BYTE_STRING_LITERAL: + case INT_LITERAL: + case FLOAT_LITERAL: + case TRUE_LITERAL: + case FALSE_LITERAL: + // stream_pos++; + return parse_meta_item_lit (); + case SUPER: + case SELF: + case CRATE: + case DOLLAR_SIGN: + case SCOPE_RESOLUTION: { + return parse_path_meta_item (); + } + default: + rust_error_at (peek_token ()->get_locus (), + "unrecognised token '%s' in meta item", + get_token_description (peek_token ()->get_id ())); + return nullptr; + } + } + + // else, check for path + if (peek_token (1)->get_id () == SCOPE_RESOLUTION) + { + // path + return parse_path_meta_item (); + } + + Identifier ident = peek_token ()->as_string (); + if (is_end_meta_item_tok (peek_token (1)->get_id ())) + { + // meta word syntax + skip_token (); + return std::unique_ptr<MetaWord> (new MetaWord (std::move (ident))); + } + + if (peek_token (1)->get_id () == EQUAL) + { + // maybe meta name value str syntax - check next 2 tokens + if (peek_token (2)->get_id () == STRING_LITERAL + && is_end_meta_item_tok (peek_token (3)->get_id ())) + { + // meta name value str syntax + std::string value = peek_token (2)->as_string (); + + skip_token (2); + + return std::unique_ptr<MetaNameValueStr> ( + new MetaNameValueStr (std::move (ident), std::move (value))); + } + else + { + // just interpret as path-based meta item + return parse_path_meta_item (); + } + } + + if (peek_token (1)->get_id () != LEFT_PAREN) + { + rust_error_at (peek_token (1)->get_locus (), + "unexpected token '%s' after identifier in attribute", + get_token_description (peek_token (1)->get_id ())); + return nullptr; + } + + /* HACK: parse parenthesised sequence, and then try conversions to other + * stuff */ + std::vector<std::unique_ptr<MetaItemInner> > meta_items + = parse_meta_item_seq (); + + // pass for meta name value str + std::vector<MetaNameValueStr> meta_name_value_str_items; + for (const auto &item : meta_items) + { + std::unique_ptr<MetaNameValueStr> converted_item + = item->to_meta_name_value_str (); + if (converted_item == nullptr) + { + meta_name_value_str_items.clear (); + break; + } + meta_name_value_str_items.push_back (std::move (*converted_item)); + } + // if valid, return this + if (!meta_name_value_str_items.empty ()) + { + return std::unique_ptr<MetaListNameValueStr> ( + new MetaListNameValueStr (std::move (ident), + std::move (meta_name_value_str_items))); + } + + // pass for meta list idents + /*std::vector<Identifier> ident_items; + for (const auto& item : meta_items) { + std::unique_ptr<Identifier> converted_ident(item->to_ident_item()); + if (converted_ident == nullptr) { + ident_items.clear(); + break; + } + ident_items.push_back(std::move(*converted_ident)); + } + // if valid return this + if (!ident_items.empty()) { + return std::unique_ptr<MetaListIdents>(new + MetaListIdents(std::move(ident), + std::move(ident_items))); + }*/ + // as currently no meta list ident, currently no path. may change in future + + // pass for meta list paths + std::vector<SimplePath> path_items; + for (const auto &item : meta_items) + { + SimplePath converted_path (item->to_path_item ()); + if (converted_path.is_empty ()) + { + path_items.clear (); + break; + } + path_items.push_back (std::move (converted_path)); + } + if (!path_items.empty ()) + { + return std::unique_ptr<MetaListPaths> ( + new MetaListPaths (std::move (ident), std::move (path_items))); + } + + rust_error_at (Linemap::unknown_location (), + "failed to parse any meta item inner"); + return nullptr; +} + +bool +MacroParser::is_end_meta_item_tok (TokenId id) const +{ + return id == COMMA || id == RIGHT_PAREN; +} + +std::unique_ptr<MetaItem> +MacroParser::parse_path_meta_item () +{ + SimplePath path = parse_simple_path (); + if (path.is_empty ()) + { + rust_error_at (peek_token ()->get_locus (), + "failed to parse simple path in attribute"); + return nullptr; + } + + switch (peek_token ()->get_id ()) + { + case LEFT_PAREN: { + std::vector<std::unique_ptr<MetaItemInner> > meta_items + = parse_meta_item_seq (); + + return std::unique_ptr<MetaItemSeq> ( + new MetaItemSeq (std::move (path), std::move (meta_items))); + } + case EQUAL: { + skip_token (); + + Location locus = peek_token ()->get_locus (); + Literal lit = parse_literal (); + if (lit.is_error ()) + { + rust_error_at (peek_token ()->get_locus (), + "failed to parse literal in attribute"); + return nullptr; + } + LiteralExpr expr (Analysis::NodeMapping::get_error (), std::move (lit), + locus); + // stream_pos++; + /* shouldn't be required anymore due to parsing literal actually + * skipping the token */ + return std::unique_ptr<MetaItemPathLit> ( + new MetaItemPathLit (std::move (path), std::move (expr))); + } + case COMMA: + // just simple path + return std::unique_ptr<MetaItemPath> ( + new MetaItemPath (std::move (path))); + default: + rust_error_at (peek_token ()->get_locus (), + "unrecognised token '%s' in meta item", + get_token_description (peek_token ()->get_id ())); + return nullptr; + } +} + +/* Parses a parenthesised sequence of meta item inners. Parentheses are + * required here. */ +std::vector<std::unique_ptr<MetaItemInner> > +MacroParser::parse_meta_item_seq () +{ + if (stream_pos != 0) + { + // warning? + fprintf (stderr, + "WARNING: stream pos for parse_meta_item_seq is not 0!\n"); + } + + // int i = 0; + int vec_length = token_stream.size (); + std::vector<std::unique_ptr<MetaItemInner> > meta_items; + + if (peek_token ()->get_id () != LEFT_PAREN) + { + rust_error_at (peek_token ()->get_locus (), + "missing left paren in delim token tree"); + return {}; + } + skip_token (); + + while (stream_pos < vec_length && peek_token ()->get_id () != RIGHT_PAREN) + { + std::unique_ptr<MetaItemInner> inner = parse_meta_item_inner (); + if (inner == nullptr) + { + rust_error_at (peek_token ()->get_locus (), + "failed to parse inner meta item in attribute"); + return {}; + } + meta_items.push_back (std::move (inner)); + + if (peek_token ()->get_id () != COMMA) + { + break; + } + skip_token (); + } + + if (peek_token ()->get_id () != RIGHT_PAREN) + { + rust_error_at (peek_token ()->get_locus (), + "missing right paren in delim token tree"); + return {}; + } + skip_token (); + + return meta_items; +} + +/* Collects any nested token trees into a flat token stream, suitable for + * parsing. */ +std::vector<std::unique_ptr<Token> > +DelimTokenTree::to_token_stream () const +{ + std::vector<std::unique_ptr<Token> > tokens; + + // simulate presence of delimiters + tokens.push_back ( + std::unique_ptr<Token> (new Token (LEFT_PAREN, Linemap::unknown_location (), + "", CORETYPE_UNKNOWN))); + + for (const auto &tree : token_trees) + { + std::vector<std::unique_ptr<Token> > stream = tree->to_token_stream (); + + tokens.insert (tokens.end (), std::make_move_iterator (stream.begin ()), + std::make_move_iterator (stream.end ())); + } + + tokens.push_back (std::unique_ptr<Token> ( + new Token (RIGHT_PAREN, Linemap::unknown_location (), "", + CORETYPE_UNKNOWN))); + + tokens.shrink_to_fit (); + + return tokens; +} + +Literal +MacroParser::parse_literal () +{ + const std::unique_ptr<Token> &tok = peek_token (); + switch (tok->get_id ()) + { + case CHAR_LITERAL: + skip_token (); + return Literal (tok->as_string (), Literal::CHAR); + case STRING_LITERAL: + skip_token (); + return Literal (tok->as_string (), Literal::STRING); + case BYTE_CHAR_LITERAL: + skip_token (); + return Literal (tok->as_string (), Literal::BYTE); + case BYTE_STRING_LITERAL: + skip_token (); + return Literal (tok->as_string (), Literal::BYTE_STRING); + case INT_LITERAL: + skip_token (); + return Literal (tok->as_string (), Literal::INT); + case FLOAT_LITERAL: + skip_token (); + return Literal (tok->as_string (), Literal::FLOAT); + case TRUE_LITERAL: + skip_token (); + return Literal ("true", Literal::BOOL); + case FALSE_LITERAL: + skip_token (); + return Literal ("false", Literal::BOOL); + default: + rust_error_at (tok->get_locus (), "expected literal - found '%s'", + get_token_description (tok->get_id ())); + return Literal::create_error (); + } +} + +SimplePath +MacroParser::parse_simple_path () +{ + bool has_opening_scope_res = false; + if (peek_token ()->get_id () == SCOPE_RESOLUTION) + { + has_opening_scope_res = true; + skip_token (); + } + + std::vector<SimplePathSegment> segments; + + SimplePathSegment segment = parse_simple_path_segment (); + if (segment.is_error ()) + { + rust_error_at ( + peek_token ()->get_locus (), + "failed to parse simple path segment in attribute simple path"); + return SimplePath::create_empty (); + } + segments.push_back (std::move (segment)); + + while (peek_token ()->get_id () == SCOPE_RESOLUTION) + { + skip_token (); + + SimplePathSegment segment = parse_simple_path_segment (); + if (segment.is_error ()) + { + rust_error_at ( + peek_token ()->get_locus (), + "failed to parse simple path segment in attribute simple path"); + return SimplePath::create_empty (); + } + segments.push_back (std::move (segment)); + } + segments.shrink_to_fit (); + + return SimplePath (std::move (segments), has_opening_scope_res); +} + +SimplePathSegment +MacroParser::parse_simple_path_segment () +{ + const std::unique_ptr<Token> &tok = peek_token (); + switch (tok->get_id ()) + { + case IDENTIFIER: + skip_token (); + return SimplePathSegment (tok->as_string (), tok->get_locus ()); + case SUPER: + skip_token (); + return SimplePathSegment ("super", tok->get_locus ()); + case SELF: + skip_token (); + return SimplePathSegment ("self", tok->get_locus ()); + case CRATE: + skip_token (); + return SimplePathSegment ("crate", tok->get_locus ()); + case DOLLAR_SIGN: + if (peek_token (1)->get_id () == CRATE) + { + skip_token (1); + return SimplePathSegment ("$crate", tok->get_locus ()); + } + gcc_fallthrough (); + default: + rust_error_at (tok->get_locus (), + "unexpected token '%s' in simple path segment", + get_token_description (tok->get_id ())); + return SimplePathSegment::create_error (); + } +} + +std::unique_ptr<MetaItemLitExpr> +MacroParser::parse_meta_item_lit () +{ + Location locus = peek_token ()->get_locus (); + LiteralExpr lit_expr (Analysis::NodeMapping::get_error (), parse_literal (), + locus); + return std::unique_ptr<MetaItemLitExpr> ( + new MetaItemLitExpr (std::move (lit_expr))); +} + +std::vector<std::unique_ptr<Token> > +Token::to_token_stream () const +{ + /* initialisation list doesn't work as it needs copy constructor, so have to + * do this */ + std::vector<std::unique_ptr<Token> > dummy_vector; + dummy_vector.reserve (1); + dummy_vector.push_back (std::unique_ptr<Token> (clone_token_impl ())); + return dummy_vector; +} + +Attribute +MetaNameValueStr::to_attribute () const +{ + LiteralExpr lit_expr (Analysis::NodeMapping::get_error (), str, + Literal::LitType::STRING, Location ()); + return Attribute (SimplePath::from_str (ident), + std::unique_ptr<AttrInputLiteral> ( + new AttrInputLiteral (std::move (lit_expr)))); +} + +Attribute +MetaItemPath::to_attribute () const +{ + return Attribute (path, nullptr); +} + +Attribute +MetaItemSeq::to_attribute () const +{ + std::vector<std::unique_ptr<MetaItemInner> > new_seq; + new_seq.reserve (seq.size ()); + for (const auto &e : seq) + new_seq.push_back (e->clone_meta_item_inner ()); + + std::unique_ptr<AttrInputMetaItemContainer> new_seq_container ( + new AttrInputMetaItemContainer (std::move (new_seq))); + return Attribute (path, std::move (new_seq_container)); +} + +Attribute +MetaWord::to_attribute () const +{ + return Attribute (SimplePath::from_str (ident), nullptr); +} + +Attribute +MetaListPaths::to_attribute () const +{ + /* probably one of the most annoying conversions - have to lose specificity by + * turning it into just AttrInputMetaItemContainer (i.e. paths-only nature is + * no longer known). If conversions back are required, might have to do a + * "check all are paths" pass or something. */ + + std::vector<std::unique_ptr<MetaItemInner> > new_seq; + new_seq.reserve (paths.size ()); + for (const auto &e : paths) + new_seq.push_back (std::unique_ptr<MetaItemPath> (new MetaItemPath (e))); + + std::unique_ptr<AttrInputMetaItemContainer> new_seq_container ( + new AttrInputMetaItemContainer (std::move (new_seq))); + return Attribute (SimplePath::from_str (ident), + std::move (new_seq_container)); +} + +Attribute +MetaListNameValueStr::to_attribute () const +{ + std::vector<std::unique_ptr<MetaItemInner> > new_seq; + new_seq.reserve (strs.size ()); + for (const auto &e : strs) + new_seq.push_back ( + std::unique_ptr<MetaNameValueStr> (new MetaNameValueStr (e))); + + std::unique_ptr<AttrInputMetaItemContainer> new_seq_container ( + new AttrInputMetaItemContainer (std::move (new_seq))); + return Attribute (SimplePath::from_str (ident), + std::move (new_seq_container)); +} + +Attribute +MetaItemPathLit::to_attribute () const +{ + return Attribute (path, std::unique_ptr<AttrInputLiteral> ( + new AttrInputLiteral (lit))); +} + +/* Visitor implementations - these are short but inlining can't happen anyway + * due to virtual functions and I didn't want to make the ast header includes + * any longer than they already are. */ + +void +Token::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +DelimTokenTree::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IdentifierExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +Lifetime::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +LifetimeParam::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MacroInvocationSemi::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +PathInExpression::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TypePathSegment::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TypePathSegmentGeneric::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TypePathSegmentFunction::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TypePath::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +QualifiedPathInExpression::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +QualifiedPathInType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +LiteralExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +AttrInputLiteral::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MetaItemLitExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MetaItemPathLit::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +BorrowExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +DereferenceExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ErrorPropagationExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +NegationExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ArithmeticOrLogicalExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ComparisonExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +LazyBooleanExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TypeCastExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +AssignmentExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +CompoundAssignmentExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +GroupedExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ArrayElemsValues::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ArrayElemsCopied::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ArrayExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ArrayIndexExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TupleExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TupleIndexExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructExprStruct::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructExprFieldIdentifier::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructExprFieldIdentifierValue::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructExprFieldIndexValue::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructExprStructFields::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructExprStructBase::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructExprTuple::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructExprUnit::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumExprFieldIdentifier::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumExprFieldIdentifierValue::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumExprFieldIndexValue::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumExprStruct::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumExprTuple::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumExprFieldless::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +CallExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MethodCallExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +FieldAccessExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ClosureExprInner::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +BlockExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ClosureExprInnerTyped::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ContinueExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +BreakExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangeFromToExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangeFromExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangeToExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangeFullExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangeFromToInclExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangeToInclExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ReturnExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +UnsafeBlockExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +LoopExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +WhileLoopExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +WhileLetLoopExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ForLoopExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IfExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IfExprConseqElse::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IfExprConseqIf::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IfExprConseqIfLet::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IfLetExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IfLetExprConseqElse::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IfLetExprConseqIf::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IfLetExprConseqIfLet::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +/*void +MatchCaseBlockExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MatchCaseExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +}*/ + +void +MatchExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +AwaitExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +AsyncBlockExpr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TypeParam::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +LifetimeWhereClauseItem::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TypeBoundWhereClauseItem::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +Method::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ModuleBodied::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ModuleNoBody::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ExternCrate::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +UseTreeGlob::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +UseTreeList::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +UseTreeRebind::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +UseDeclaration::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +Function::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TypeAlias::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructStruct::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TupleStruct::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumItem::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumItemTuple::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumItemStruct::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EnumItemDiscriminant::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +Enum::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +Union::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ConstantItem::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StaticItem::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TraitItemFunc::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TraitItemMethod::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TraitItemConst::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TraitItemType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +Trait::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +InherentImpl::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TraitImpl::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ExternalStaticItem::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ExternalFunctionItem::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ExternBlock::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MacroMatchFragment::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MacroMatchRepetition::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MacroMatcher::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MacroRulesDefinition::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MacroInvocation::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +LiteralPattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +IdentifierPattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +WildcardPattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangePatternBoundLiteral::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangePatternBoundPath::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangePatternBoundQualPath::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RangePattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ReferencePattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructPatternFieldTuplePat::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructPatternFieldIdentPat::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructPatternFieldIdent::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +StructPattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TupleStructItemsNoRange::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TupleStructItemsRange::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TupleStructPattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TuplePatternItemsMultiple::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TuplePatternItemsRanged::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TuplePattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +GroupedPattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +SlicePattern::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +EmptyStmt::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +LetStmt::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ExprStmtWithoutBlock::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ExprStmtWithBlock::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TraitBound::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ImplTraitType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TraitObjectType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ParenthesisedType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ImplTraitTypeOneBound::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TraitObjectTypeOneBound::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +TupleType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +NeverType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +RawPointerType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ReferenceType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +ArrayType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +SliceType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +InferredType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +BareFunctionType::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MetaItemSeq::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MetaItemPath::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MetaListPaths::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MetaNameValueStr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MetaListNameValueStr::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +AttrInputMetaItemContainer::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} + +void +MetaWord::accept_vis (HIRVisitor &vis) +{ + vis.visit (*this); +} +} // namespace HIR +} // namespace Rust diff --git a/gcc/rust/hir/tree/rust-hir-full.h b/gcc/rust/hir/tree/rust-hir-full.h new file mode 100644 index 0000000..82525cd --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-full.h @@ -0,0 +1,32 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_FULL_H +#define RUST_HIR_FULL_H + +// Use as a fast way of including all aspects of the HIR (i.e. all headers) +#include "rust-hir.h" +#include "rust-hir-expr.h" +#include "rust-hir-item.h" +#include "rust-hir-path.h" +#include "rust-hir-pattern.h" +#include "rust-hir-stmt.h" +#include "rust-hir-type.h" +#include "rust-hir-macro.h" + +#endif // RUST_HIR_FULL_H diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h new file mode 100644 index 0000000..e0477f4 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -0,0 +1,3259 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_ITEM_H +#define RUST_HIR_ITEM_H + +#include "rust-hir.h" +#include "rust-hir-path.h" + +namespace Rust { +namespace HIR { +// forward decls +class BlockExpr; +class TypePath; +class MacroInvocationSemi; + +// A type generic parameter (as opposed to a lifetime generic parameter) +class TypeParam : public GenericParam +{ + // bool has_outer_attribute; + // std::unique_ptr<Attribute> outer_attr; + Attribute outer_attr; + + Identifier type_representation; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + std::vector<std::unique_ptr<TypeParamBound> > + type_param_bounds; // inlined form + + // bool has_type; + std::unique_ptr<Type> type; + + Location locus; + +public: + // Returns whether the type of the type param has been specified. + bool has_type () const { return type != nullptr; } + + // Returns whether the type param has type param bounds. + bool has_type_param_bounds () const { return !type_param_bounds.empty (); } + + // Returns whether the type param has an outer attribute. + bool has_outer_attribute () const { return !outer_attr.is_empty (); } + + TypeParam (Identifier type_representation, Location locus = Location (), + std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds + = std::vector<std::unique_ptr<TypeParamBound> > (), + std::unique_ptr<Type> type = nullptr, + Attribute outer_attr = Attribute::create_empty ()) + : outer_attr (std::move (outer_attr)), + type_representation (std::move (type_representation)), + type_param_bounds (std::move (type_param_bounds)), + type (std::move (type)), locus (locus) + {} + + // Copy constructor uses clone + TypeParam (TypeParam const &other) + : outer_attr (other.outer_attr), + type_representation (other.type_representation), + type (other.type->clone_type ()), locus (other.locus) + { + 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 + TypeParam &operator= (TypeParam const &other) + { + type_representation = other.type_representation; + // type_param_bounds = other.type_param_bounds; + type = other.type->clone_type (); + outer_attr = other.outer_attr; + locus = other.locus; + + 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 + TypeParam (TypeParam &&other) = default; + TypeParam &operator= (TypeParam &&other) = default; + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + TypeParam *clone_generic_param_impl () const override + { + return new TypeParam (*this); + } +}; + +/* "where" clause item base. Abstract - use LifetimeWhereClauseItem, + * TypeBoundWhereClauseItem */ +class WhereClauseItem +{ +public: + virtual ~WhereClauseItem () {} + + // Unique pointer custom clone function + std::unique_ptr<WhereClauseItem> clone_where_clause_item () const + { + return std::unique_ptr<WhereClauseItem> (clone_where_clause_item_impl ()); + } + + virtual std::string as_string () const = 0; + + virtual void accept_vis (HIRVisitor &vis) = 0; + +protected: + // Clone function implementation as pure virtual method + virtual WhereClauseItem *clone_where_clause_item_impl () const = 0; +}; + +// A lifetime where clause item +class LifetimeWhereClauseItem : public WhereClauseItem +{ + Lifetime lifetime; + + // LifetimeBounds lifetime_bounds; + std::vector<Lifetime> lifetime_bounds; // inlined lifetime bounds + + // should this store location info? + +public: + LifetimeWhereClauseItem (Lifetime lifetime, + std::vector<Lifetime> lifetime_bounds) + : lifetime (std::move (lifetime)), + lifetime_bounds (std::move (lifetime_bounds)) + {} + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + LifetimeWhereClauseItem *clone_where_clause_item_impl () const override + { + return new LifetimeWhereClauseItem (*this); + } +}; + +// A type bound where clause item +class TypeBoundWhereClauseItem : public WhereClauseItem +{ + // bool has_for_lifetimes; + // LifetimeParams for_lifetimes; + std::vector<LifetimeParam> for_lifetimes; // inlined + + std::unique_ptr<Type> bound_type; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + std::vector<std::unique_ptr<TypeParamBound> > + type_param_bounds; // inlined form + + // should this store location info? + +public: + // Returns whether the item has ForLifetimes + bool has_for_lifetimes () const { return !for_lifetimes.empty (); } + + // Returns whether the item has type param bounds + bool has_type_param_bounds () const { return !type_param_bounds.empty (); } + + TypeBoundWhereClauseItem ( + std::vector<LifetimeParam> for_lifetimes, std::unique_ptr<Type> bound_type, + std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds) + : for_lifetimes (std::move (for_lifetimes)), + bound_type (std::move (bound_type)), + type_param_bounds (std::move (type_param_bounds)) + {} + + // Copy constructor requires clone + TypeBoundWhereClauseItem (TypeBoundWhereClauseItem const &other) + : for_lifetimes (other.for_lifetimes), + bound_type (other.bound_type->clone_type ()) + { + 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 ()); + } + + // Overload assignment operator to clone + TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem const &other) + { + for_lifetimes = other.for_lifetimes; + bound_type = other.bound_type->clone_type (); + + 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 + TypeBoundWhereClauseItem (TypeBoundWhereClauseItem &&other) = default; + TypeBoundWhereClauseItem &operator= (TypeBoundWhereClauseItem &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + TypeBoundWhereClauseItem *clone_where_clause_item_impl () const override + { + return new TypeBoundWhereClauseItem (*this); + } +}; + +// A where clause +struct WhereClause +{ +private: + std::vector<std::unique_ptr<WhereClauseItem> > where_clause_items; + + // should this store location info? + +public: + WhereClause ( + std::vector<std::unique_ptr<WhereClauseItem> > where_clause_items) + : where_clause_items (std::move (where_clause_items)) + {} + + // copy constructor with vector clone + WhereClause (WhereClause const &other) + { + where_clause_items.reserve (other.where_clause_items.size ()); + for (const auto &e : other.where_clause_items) + where_clause_items.push_back (e->clone_where_clause_item ()); + } + + // overloaded assignment operator with vector clone + WhereClause &operator= (WhereClause const &other) + { + where_clause_items.reserve (other.where_clause_items.size ()); + for (const auto &e : other.where_clause_items) + where_clause_items.push_back (e->clone_where_clause_item ()); + + return *this; + } + + // move constructors + WhereClause (WhereClause &&other) = default; + WhereClause &operator= (WhereClause &&other) = default; + + // Creates a WhereClause with no items. + static WhereClause create_empty () + { + return WhereClause (std::vector<std::unique_ptr<WhereClauseItem> > ()); + } + + // Returns whether the WhereClause has no items. + bool is_empty () const { return where_clause_items.empty (); } + + std::string as_string () const; +}; + +// A self parameter in a method +struct SelfParam +{ +private: + bool has_ref; + bool is_mut; + // bool has_lifetime; // only possible if also ref + Lifetime lifetime; + + // bool has_type; // only possible if not ref + std::unique_ptr<Type> type; + + Location locus; + + // Unrestricted constructor used for error state + SelfParam (Lifetime lifetime, bool has_ref, bool is_mut, Type *type) + : has_ref (has_ref), is_mut (is_mut), lifetime (std::move (lifetime)), + type (type) + {} + // this is ok as no outside classes can ever call this + +public: + // Returns whether the self-param has a type field. + bool has_type () const { return type != nullptr; } + + // Returns whether the self-param has a valid lifetime. + bool has_lifetime () const { return !lifetime.is_error (); } + + // Returns whether the self-param is in an error state. + bool is_error () const + { + return has_type () && has_lifetime (); + // not having either is not an error + } + + // Type-based self parameter (not ref, no lifetime) + SelfParam (std::unique_ptr<Type> type, bool is_mut, Location locus) + : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()), + type (std::move (type)), locus (locus) + {} + + // Lifetime-based self parameter (is ref, no type) + SelfParam (Lifetime lifetime, bool is_mut, Location locus) + : has_ref (true), is_mut (is_mut), lifetime (std::move (lifetime)), + locus (locus) + {} + + // Copy constructor requires clone + SelfParam (SelfParam const &other) + : has_ref (other.has_ref), is_mut (other.is_mut), lifetime (other.lifetime), + locus (other.locus) + { + if (other.type != nullptr) + type = other.type->clone_type (); + } + + // Overload assignment operator to use clone + SelfParam &operator= (SelfParam const &other) + { + if (other.type != nullptr) + type = other.type->clone_type (); + is_mut = other.is_mut; + has_ref = other.has_ref; + lifetime = other.lifetime; + locus = other.locus; + + return *this; + } + + // move constructors + SelfParam (SelfParam &&other) = default; + SelfParam &operator= (SelfParam &&other) = default; + + std::string as_string () const; + + Location get_locus () const { return locus; } +}; + +// Qualifiers for function, i.e. const, unsafe, extern etc. +struct FunctionQualifiers +{ +public: + /* Whether the function is neither const nor async, const only, or async + * only. */ + enum AsyncConstStatus + { + NONE, + CONST, + ASYNC + }; + +private: + AsyncConstStatus const_status; + bool has_unsafe; + bool has_extern; + std::string extern_abi; // e.g. extern "C" fn() -> i32 {} + // TODO: maybe ensure that extern_abi only exists if extern exists? + + // should this store location info? + +public: + FunctionQualifiers (AsyncConstStatus const_status, bool has_unsafe, + bool has_extern = false, + std::string extern_abi = std::string ()) + : const_status (const_status), has_unsafe (has_unsafe), + has_extern (has_extern), extern_abi (std::move (extern_abi)) + { + if (!this->extern_abi.empty ()) + { + // having extern is required; not having it is an implementation error + gcc_assert (has_extern); + } + } + + std::string as_string () const; +}; + +// A function parameter +struct FunctionParam +{ +public: + std::unique_ptr<Pattern> param_name; + std::unique_ptr<Type> type; + + Location locus; + Analysis::NodeMapping mappings; + + FunctionParam (Analysis::NodeMapping mappings, + std::unique_ptr<Pattern> param_name, + std::unique_ptr<Type> param_type, Location locus) + : param_name (std::move (param_name)), type (std::move (param_type)), + locus (locus), mappings (mappings) + {} + + // Copy constructor uses clone + FunctionParam (FunctionParam const &other) + : param_name (other.param_name->clone_pattern ()), + type (other.type->clone_type ()), locus (other.locus), + mappings (other.mappings) + {} + + // Overload assignment operator to use clone + FunctionParam &operator= (FunctionParam const &other) + { + param_name = other.param_name->clone_pattern (); + type = other.type->clone_type (); + locus = other.locus; + mappings = other.mappings; + + return *this; + } + + // move constructors + FunctionParam (FunctionParam &&other) = default; + FunctionParam &operator= (FunctionParam &&other) = default; + + std::string as_string () const; + + Location get_locus () const { return locus; } + + Pattern *get_param_name () { return param_name.get (); } + + Type *get_type () { return type.get (); } + + Analysis::NodeMapping *get_mappings () { return &mappings; } +}; + +// Visibility of item - if the item has it, then it is some form of public +struct Visibility +{ +public: + enum PublicVisType + { + NONE, + CRATE, + SELF, + SUPER, + IN_PATH + }; + +private: + // if vis is public, one of these + PublicVisType public_vis_type; + // Only assigned if public_vis_type is IN_PATH + SimplePath in_path; + + // should this store location info? + +public: + // Creates a Visibility - TODO make constructor protected or private? + Visibility (PublicVisType public_vis_type, SimplePath in_path) + : public_vis_type (public_vis_type), in_path (std::move (in_path)) + {} + + // Returns whether visibility is in an error state. + bool is_error () const + { + return public_vis_type == IN_PATH && in_path.is_empty (); + } + + // Creates an error visibility. + static Visibility create_error () + { + return Visibility (IN_PATH, SimplePath::create_empty ()); + } + + // Unique pointer custom clone function + /*std::unique_ptr<Visibility> clone_visibility() const { + return std::unique_ptr<Visibility>(clone_visibility_impl()); + }*/ + + /* TODO: think of a way to only allow valid Visibility states - polymorphism + * is one idea but may be too resource-intensive. */ + + // Creates a public visibility with no further features/arguments. + static Visibility create_public () + { + return Visibility (NONE, SimplePath::create_empty ()); + } + + // Creates a public visibility with crate-relative paths or whatever. + static Visibility create_crate () + { + return Visibility (CRATE, SimplePath::create_empty ()); + } + + // Creates a public visibility with self-relative paths or whatever. + static Visibility create_self () + { + return Visibility (SELF, SimplePath::create_empty ()); + } + + // Creates a public visibility with parent module-relative paths or + // whatever. + static Visibility create_super () + { + return Visibility (SUPER, SimplePath::create_empty ()); + } + + // Creates a public visibility with a given path or whatever. + static Visibility create_in_path (SimplePath in_path) + { + return Visibility (IN_PATH, std::move (in_path)); + } + + std::string as_string () const; + +protected: + // Clone function implementation - not currently virtual but may be if + // polymorphism used + /*virtual*/ Visibility *clone_visibility_impl () const + { + return new Visibility (*this); + } +}; + +// A method (function belonging to a type) +class Method : public InherentImplItem, public TraitImplItem +{ + // moved from impl items for consistency + std::vector<Attribute> outer_attrs; + Visibility vis; + + FunctionQualifiers qualifiers; + Identifier method_name; + + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + SelfParam self_param; + + // bool has_params; + // FunctionParams function_params; + std::vector<FunctionParam> function_params; // inlined + + // bool has_return_type; + // FunctionReturnType return_type; + std::unique_ptr<Type> return_type; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::unique_ptr<BlockExpr> expr; + + Location locus; + +public: + // Returns whether the method has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether the method has parameters. + bool has_params () const { return !function_params.empty (); } + + // Returns whether the method has a return type (void otherwise). + bool has_return_type () const { return return_type != nullptr; } + + // Returns whether the where clause exists (i.e. has items) + bool has_where_clause () const { return !where_clause.is_empty (); } + + // Returns whether method has a non-default visibility. + bool has_visibility () const { return !vis.is_error (); } + + // Mega-constructor with all possible fields + Method (Identifier method_name, FunctionQualifiers qualifiers, + std::vector<std::unique_ptr<GenericParam> > generic_params, + SelfParam self_param, std::vector<FunctionParam> function_params, + std::unique_ptr<Type> return_type, WhereClause where_clause, + std::unique_ptr<BlockExpr> function_body, Visibility vis, + std::vector<Attribute> outer_attrs, Location locus = Location ()) + : outer_attrs (std::move (outer_attrs)), vis (std::move (vis)), + qualifiers (std::move (qualifiers)), + method_name (std::move (method_name)), + generic_params (std::move (generic_params)), + self_param (std::move (self_param)), + function_params (std::move (function_params)), + return_type (std::move (return_type)), + where_clause (std::move (where_clause)), expr (std::move (function_body)), + locus (locus) + {} + + // TODO: add constructor with less fields + + // Copy constructor with clone + Method (Method const &other) + : outer_attrs (other.outer_attrs), vis (other.vis), + qualifiers (other.qualifiers), method_name (other.method_name), + self_param (other.self_param), function_params (other.function_params), + return_type (other.return_type->clone_type ()), + where_clause (other.where_clause), expr (other.expr->clone_block_expr ()), + locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Overloaded assignment operator to clone + Method &operator= (Method const &other) + { + method_name = other.method_name; + outer_attrs = other.outer_attrs; + vis = other.vis; + qualifiers = other.qualifiers; + self_param = other.self_param; + function_params = other.function_params; + return_type = other.return_type->clone_type (); + where_clause = other.where_clause; + expr = other.expr->clone_block_expr (); + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + Method (Method &&other) = default; + Method &operator= (Method &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Method *clone_inherent_impl_item_impl () const override + { + return new Method (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + Method *clone_trait_impl_item_impl () const override + { + return new Method (*this); + } +}; + +// Item that supports visibility - abstract base class +class VisItem : public Item +{ + Visibility visibility; + +protected: + // Visibility constructor + VisItem (Analysis::NodeMapping mappings, Visibility visibility, + std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) + : Item (std::move (mappings), std::move (outer_attrs)), + visibility (std::move (visibility)) + {} + + // Visibility copy constructor + VisItem (VisItem const &other) : Item (other), visibility (other.visibility) + {} + + // Overload assignment operator to clone + VisItem &operator= (VisItem const &other) + { + Item::operator= (other); + visibility = other.visibility; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + VisItem (VisItem &&other) = default; + VisItem &operator= (VisItem &&other) = default; + +public: + /* Does the item have some kind of public visibility (non-default + * visibility)? */ + bool has_visibility () const { return !visibility.is_error (); } + + Visibility &get_visibility () { return visibility; } + + std::string as_string () const override; +}; + +// Rust module item - abstract base class +class Module : public VisItem +{ + Identifier module_name; + Location locus; + +protected: + // Protected constructor + Module (Analysis::NodeMapping mappings, Identifier module_name, + Visibility visibility, Location locus, + std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) + : VisItem (std::move (mappings), std::move (visibility), + std::move (outer_attrs)), + module_name (module_name), locus (locus) + {} + +public: + std::string as_string () const override; + + Location get_locus () const { return locus; } +}; + +// Module with a body, defined in file +class ModuleBodied : public Module +{ + // bool has_inner_attrs; + std::vector<Attribute> inner_attrs; + // bool has_items; + std::vector<std::unique_ptr<Item> > items; + +public: + std::string as_string () const override; + + // Returns whether the module has items in its body. + bool has_items () const { return !items.empty (); } + + // Returns whether the module has any inner attributes. + bool has_inner_attrs () const { return !inner_attrs.empty (); } + + // Full constructor + ModuleBodied (Analysis::NodeMapping mappings, Identifier name, Location locus, + std::vector<std::unique_ptr<Item> > items + = std::vector<std::unique_ptr<Item> > (), + Visibility visibility = Visibility::create_error (), + std::vector<Attribute> inner_attrs = std::vector<Attribute> (), + std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) + : Module (std::move (mappings), std::move (name), std::move (visibility), + locus, std::move (outer_attrs)), + inner_attrs (std::move (inner_attrs)), items (std::move (items)) + {} + + // Copy constructor with vector clone + ModuleBodied (ModuleBodied const &other) + : Module (other), inner_attrs (other.inner_attrs) + { + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_item ()); + } + + // Overloaded assignment operator with vector clone + ModuleBodied &operator= (ModuleBodied const &other) + { + Module::operator= (other); + inner_attrs = other.inner_attrs; + + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_item ()); + + return *this; + } + + // move constructors + ModuleBodied (ModuleBodied &&other) = default; + ModuleBodied &operator= (ModuleBodied &&other) = default; + + void accept_vis (HIRVisitor &vis) override; + + /* Override that runs the function recursively on all items contained within + * the module. */ + void add_crate_name (std::vector<std::string> &names) const override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ModuleBodied *clone_item_impl () const override + { + return new ModuleBodied (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual ModuleBodied* clone_statement_impl() const override { + return new ModuleBodied(*this); + }*/ +}; + +// Module without a body, loaded from external file +class ModuleNoBody : public Module +{ +public: + std::string as_string () const override; + + // Full constructor + ModuleNoBody (Analysis::NodeMapping mappings, Identifier name, + Visibility visibility, std::vector<Attribute> outer_attrs, + Location locus) + : Module (std::move (mappings), std::move (name), std::move (visibility), + locus, std::move (outer_attrs)) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ModuleNoBody *clone_item_impl () const override + { + return new ModuleNoBody (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual ModuleNoBody* clone_statement_impl() const override { + return new ModuleNoBody(*this); + }*/ +}; + +// Rust extern crate declaration HIR node +class ExternCrate : public VisItem +{ + // this is either an identifier or "self", with self parsed to string + std::string referenced_crate; + // bool has_as_clause; + // AsClause as_clause; + // this is either an identifier or "_", with _ parsed to string + std::string as_clause_name; + + Location locus; + + /* e.g. + "extern crate foo as _" + "extern crate foo" + "extern crate std as cool_std" */ +public: + std::string as_string () const override; + + // Returns whether extern crate declaration has an as clause. + bool has_as_clause () const { return !as_clause_name.empty (); } + + /* Returns whether extern crate declaration references the current crate + * (i.e. self). */ + bool references_self () const { return referenced_crate == "self"; } + + // Constructor + ExternCrate (Analysis::NodeMapping mappings, std::string referenced_crate, + Visibility visibility, std::vector<Attribute> outer_attrs, + Location locus, std::string as_clause_name = std::string ()) + : VisItem (std::move (mappings), std::move (visibility), + std::move (outer_attrs)), + referenced_crate (std::move (referenced_crate)), + as_clause_name (std::move (as_clause_name)), locus (locus) + {} + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + + // Override that adds extern crate name in decl to passed list of names. + void add_crate_name (std::vector<std::string> &names) const override + { + names.push_back (referenced_crate); + } + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ExternCrate *clone_item_impl () const override + { + return new ExternCrate (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual ExternCrate* clone_statement_impl() const override { + return new ExternCrate(*this); + }*/ +}; + +// The path-ish thing referred to in a use declaration - abstract base class +class UseTree +{ + Location locus; + +public: + virtual ~UseTree () {} + + // Unique pointer custom clone function + std::unique_ptr<UseTree> clone_use_tree () const + { + return std::unique_ptr<UseTree> (clone_use_tree_impl ()); + } + + virtual std::string as_string () const = 0; + + Location get_locus () const { return locus; } + + virtual void accept_vis (HIRVisitor &vis) = 0; + +protected: + // Clone function implementation as pure virtual method + virtual UseTree *clone_use_tree_impl () const = 0; + + UseTree (Location locus) : locus (locus) {} +}; + +// Use tree with a glob (wildcard) operator +class UseTreeGlob : public UseTree +{ +public: + enum PathType + { + NO_PATH, + GLOBAL, + PATH_PREFIXED + }; + +private: + PathType glob_type; + SimplePath path; + +public: + UseTreeGlob (PathType glob_type, SimplePath path, Location locus) + : UseTree (locus), glob_type (glob_type), path (std::move (path)) + { + if (this->glob_type != PATH_PREFIXED) + { + // compiler implementation error if there is a path with a + // non-path-prefixed use tree glob + gcc_assert (!has_path ()); + } + // TODO: do path-prefixed paths also have to have a path? If so, have an + // assert for that too. + } + + /* Returns whether has path. Should be made redundant by PathType + * PATH_PREFIXED. */ + bool has_path () const { return !path.is_empty (); } + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + + /* TODO: find way to ensure only PATH_PREFIXED glob_type has path - factory + * methods? */ +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + UseTreeGlob *clone_use_tree_impl () const override + { + return new UseTreeGlob (*this); + } +}; + +// Use tree with a list of paths with a common prefix +class UseTreeList : public UseTree +{ +public: + enum PathType + { + NO_PATH, + GLOBAL, + PATH_PREFIXED + }; + +private: + PathType path_type; + SimplePath path; + + std::vector<std::unique_ptr<UseTree> > trees; + +public: + UseTreeList (PathType path_type, SimplePath path, + std::vector<std::unique_ptr<UseTree> > trees, Location locus) + : UseTree (locus), path_type (path_type), path (std::move (path)), + trees (std::move (trees)) + { + if (this->path_type != PATH_PREFIXED) + { + // compiler implementation error if there is a path with a + // non-path-prefixed use tree glob + gcc_assert (!has_path ()); + } + // TODO: do path-prefixed paths also have to have a path? If so, have an + // assert for that too. + } + + // copy constructor with vector clone + UseTreeList (UseTreeList const &other) + : UseTree (other), path_type (other.path_type), path (other.path) + { + trees.reserve (other.trees.size ()); + for (const auto &e : other.trees) + trees.push_back (e->clone_use_tree ()); + } + + // overloaded assignment operator with vector clone + UseTreeList &operator= (UseTreeList const &other) + { + UseTree::operator= (other); + path_type = other.path_type; + path = other.path; + + trees.reserve (other.trees.size ()); + for (const auto &e : other.trees) + trees.push_back (e->clone_use_tree ()); + + return *this; + } + + // move constructors + UseTreeList (UseTreeList &&other) = default; + UseTreeList &operator= (UseTreeList &&other) = default; + + // Returns whether has path. Should be made redundant by path_type. + bool has_path () const { return !path.is_empty (); } + + // Returns whether has inner tree elements. + bool has_trees () const { return !trees.empty (); } + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + + // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory + // methods? +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + UseTreeList *clone_use_tree_impl () const override + { + return new UseTreeList (*this); + } +}; + +// Use tree where it rebinds the module name as something else +class UseTreeRebind : public UseTree +{ +public: + enum NewBindType + { + NONE, + IDENTIFIER, + WILDCARD + }; + +private: + SimplePath path; + + NewBindType bind_type; + Identifier identifier; // only if NewBindType is IDENTIFIER + +public: + UseTreeRebind (NewBindType bind_type, SimplePath path, Location locus, + Identifier identifier = std::string ()) + : UseTree (locus), path (std::move (path)), bind_type (bind_type), + identifier (std::move (identifier)) + {} + + // Returns whether has path (this should always be true). + bool has_path () const { return !path.is_empty (); } + + // Returns whether has identifier (or, rather, is allowed to). + bool has_identifier () const { return bind_type == IDENTIFIER; } + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + + // TODO: find way to ensure only PATH_PREFIXED path_type has path - factory + // methods? +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + virtual UseTreeRebind *clone_use_tree_impl () const override + { + return new UseTreeRebind (*this); + } +}; + +// Rust use declaration (i.e. for modules) HIR node +class UseDeclaration : public VisItem +{ + std::unique_ptr<UseTree> use_tree; + Location locus; + +public: + std::string as_string () const override; + + UseDeclaration (Analysis::NodeMapping mappings, + std::unique_ptr<UseTree> use_tree, Visibility visibility, + std::vector<Attribute> outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (visibility), + std::move (outer_attrs)), + use_tree (std::move (use_tree)), locus (locus) + {} + + // Copy constructor with clone + UseDeclaration (UseDeclaration const &other) + : VisItem (other), use_tree (other.use_tree->clone_use_tree ()), + locus (other.locus) + {} + + // Overloaded assignment operator to clone + UseDeclaration &operator= (UseDeclaration const &other) + { + VisItem::operator= (other); + use_tree = other.use_tree->clone_use_tree (); + // visibility = other.visibility->clone_visibility(); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + UseDeclaration (UseDeclaration &&other) = default; + UseDeclaration &operator= (UseDeclaration &&other) = default; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + UseDeclaration *clone_item_impl () const override + { + return new UseDeclaration (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual UseDeclaration* clone_statement_impl() const override { + return new UseDeclaration(*this); + }*/ +}; + +// Parameters used in a function - TODO inline? +/*struct FunctionParams { + std::vector<FunctionParam> function_params; +};*/ + +class LetStmt; + +// Rust function declaration HIR node +class Function : public VisItem, public InherentImplItem, public TraitImplItem +{ +public: + FunctionQualifiers qualifiers; + Identifier function_name; + + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + // bool has_function_params; + // FunctionParams function_params; + std::vector<FunctionParam> function_params; // inlined + + // bool has_function_return_type; + std::unique_ptr<Type> return_type; + + // bool has_where_clause; + WhereClause where_clause; + + std::unique_ptr<BlockExpr> function_body; + + Location locus; + + std::string as_string () const override; + + // Returns whether function has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether function has regular parameters. + bool has_function_params () const { return !function_params.empty (); } + + // Returns whether function has return type - if not, it is void. + bool has_function_return_type () const { return return_type != nullptr; } + + // Returns whether function has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + // Mega-constructor with all possible fields + Function (Analysis::NodeMapping mappings, Identifier function_name, + FunctionQualifiers qualifiers, + std::vector<std::unique_ptr<GenericParam> > generic_params, + std::vector<FunctionParam> function_params, + std::unique_ptr<Type> return_type, WhereClause where_clause, + std::unique_ptr<BlockExpr> function_body, Visibility vis, + std::vector<Attribute> outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + qualifiers (std::move (qualifiers)), + function_name (std::move (function_name)), + generic_params (std::move (generic_params)), + function_params (std::move (function_params)), + return_type (std::move (return_type)), + where_clause (std::move (where_clause)), + function_body (std::move (function_body)), locus (locus) + {} + + // TODO: add constructor with less fields + + // Copy constructor with clone + Function (Function const &other) + : VisItem (other), qualifiers (other.qualifiers), + function_name (other.function_name), + function_params (other.function_params), + return_type (other.return_type->clone_type ()), + where_clause (other.where_clause), + function_body (other.function_body->clone_block_expr ()), + locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Overloaded assignment operator to clone + Function &operator= (Function const &other) + { + VisItem::operator= (other); + function_name = other.function_name; + qualifiers = other.qualifiers; + // generic_params = other.generic_params; + function_params = other.function_params; + return_type = other.return_type->clone_type (); + where_clause = other.where_clause; + function_body = other.function_body->clone_block_expr (); + // visibility = other.visibility->clone_visibility(); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + Function (Function &&other) = default; + Function &operator= (Function &&other) = default; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Function *clone_item_impl () const override { return new Function (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + Function *clone_inherent_impl_item_impl () const override + { + return new Function (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + Function *clone_trait_impl_item_impl () const override + { + return new Function (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual Function* clone_statement_impl() const override { + return new Function(*this); + }*/ +}; + +// Rust type alias (i.e. typedef) HIR node +class TypeAlias : public VisItem, public TraitImplItem +{ + Identifier new_type_name; + + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::unique_ptr<Type> existing_type; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether type alias has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether type alias has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + // Mega-constructor with all possible fields + TypeAlias (Analysis::NodeMapping mappings, Identifier new_type_name, + std::vector<std::unique_ptr<GenericParam> > generic_params, + WhereClause where_clause, std::unique_ptr<Type> existing_type, + Visibility vis, std::vector<Attribute> outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + new_type_name (std::move (new_type_name)), + generic_params (std::move (generic_params)), + where_clause (std::move (where_clause)), + existing_type (std::move (existing_type)), locus (locus) + {} + + // Copy constructor + TypeAlias (TypeAlias const &other) + : VisItem (other), new_type_name (other.new_type_name), + where_clause (other.where_clause), + existing_type (other.existing_type->clone_type ()), locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Overloaded assignment operator to clone + TypeAlias &operator= (TypeAlias const &other) + { + VisItem::operator= (other); + new_type_name = other.new_type_name; + // generic_params = other.generic_params; + where_clause = other.where_clause; + existing_type = other.existing_type->clone_type (); + // visibility = other.visibility->clone_visibility(); + // outer_attrs = other.outer_attrs; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + TypeAlias (TypeAlias &&other) = default; + TypeAlias &operator= (TypeAlias &&other) = default; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + TypeAlias *clone_item_impl () const override { return new TypeAlias (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + TypeAlias *clone_trait_impl_item_impl () const override + { + return new TypeAlias (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual TypeAlias* clone_statement_impl() const override { + return new TypeAlias(*this); + }*/ +}; + +// Rust base struct declaration HIR node - abstract base class +class Struct : public VisItem +{ +public: + // protected to enable access by derived classes - allows better as_string + Identifier struct_name; + + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + Location locus; + + // Returns whether struct has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether struct has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + Location get_locus () const { return locus; } + +protected: + Struct (Analysis::NodeMapping mappings, Identifier struct_name, + std::vector<std::unique_ptr<GenericParam> > generic_params, + WhereClause where_clause, Visibility vis, Location locus, + std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + struct_name (std::move (struct_name)), + generic_params (std::move (generic_params)), + where_clause (std::move (where_clause)), locus (locus) + {} + + // Copy constructor with vector clone + Struct (Struct const &other) + : VisItem (other), struct_name (other.struct_name), + where_clause (other.where_clause), locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Overloaded assignment operator with vector clone + Struct &operator= (Struct const &other) + { + VisItem::operator= (other); + struct_name = other.struct_name; + where_clause = other.where_clause; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + Struct (Struct &&other) = default; + Struct &operator= (Struct &&other) = default; +}; + +// A single field in a struct +struct StructField +{ +public: + // bool has_outer_attributes; + std::vector<Attribute> outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier field_name; + std::unique_ptr<Type> field_type; + + // should this store location info? + + // Returns whether struct field has any outer attributes. + bool has_outer_attributes () const { return !outer_attrs.empty (); } + + // Returns whether struct field has a non-private (non-default) visibility. + bool has_visibility () const { return !visibility.is_error (); } + + StructField (Identifier field_name, std::unique_ptr<Type> field_type, + Visibility vis, + std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) + : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), + field_name (std::move (field_name)), field_type (std::move (field_type)) + {} + + // Copy constructor + StructField (StructField const &other) + : outer_attrs (other.outer_attrs), visibility (other.visibility), + field_name (other.field_name), + field_type (other.field_type->clone_type ()) + {} + + ~StructField () = default; + + // Overloaded assignment operator to clone + StructField &operator= (StructField const &other) + { + field_name = other.field_name; + field_type = other.field_type->clone_type (); + visibility = other.visibility; + outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + StructField (StructField &&other) = default; + StructField &operator= (StructField &&other) = default; + + // Returns whether struct field is in an error state. + bool is_error () const + { + return field_name.empty () && field_type == nullptr; + // this should really be an or since neither are allowed + } + + // Creates an error state struct field. + static StructField create_error () + { + return StructField (std::string (""), nullptr, Visibility::create_error ()); + } + + std::string as_string () const; +}; + +// Rust struct declaration with true struct type HIR node +class StructStruct : public Struct +{ +public: + std::vector<StructField> fields; + bool is_unit; + + std::string as_string () const override; + + // Mega-constructor with all possible fields + StructStruct (Analysis::NodeMapping mappings, std::vector<StructField> fields, + Identifier struct_name, + std::vector<std::unique_ptr<GenericParam> > generic_params, + WhereClause where_clause, bool is_unit, Visibility vis, + std::vector<Attribute> outer_attrs, Location locus) + : Struct (std::move (mappings), std::move (struct_name), + std::move (generic_params), std::move (where_clause), + std::move (vis), locus, std::move (outer_attrs)), + fields (std::move (fields)), is_unit (is_unit) + {} + + // Unit struct constructor + StructStruct (Analysis::NodeMapping mappings, Identifier struct_name, + std::vector<std::unique_ptr<GenericParam> > generic_params, + WhereClause where_clause, Visibility vis, + std::vector<Attribute> outer_attrs, Location locus) + : Struct (std::move (mappings), std::move (struct_name), + std::move (generic_params), std::move (where_clause), + std::move (vis), locus, std::move (outer_attrs)), + is_unit (true) + {} + // TODO: can a unit struct have generic fields? assuming yes for now. + + /* Returns whether the struct is a unit struct - struct defined without + * fields. This is important because it also means an implicit constant of its + * type is defined. */ + bool is_unit_struct () const { return is_unit; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + StructStruct *clone_item_impl () const override + { + return new StructStruct (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual StructStruct* clone_statement_impl() const override { + return new StructStruct(*this); + }*/ +}; + +// A single field in a tuple +struct TupleField +{ +private: + // bool has_outer_attributes; + std::vector<Attribute> outer_attrs; + + // bool has_visibility; + Visibility visibility; + + std::unique_ptr<Type> field_type; + + // should this store location info? + +public: + // Returns whether tuple field has outer attributes. + bool has_outer_attributes () const { return !outer_attrs.empty (); } + + /* Returns whether tuple field has a non-default visibility (i.e. a public + * one) */ + bool has_visibility () const { return !visibility.is_error (); } + + // Complete constructor + TupleField (std::unique_ptr<Type> field_type, Visibility vis, + std::vector<Attribute> outer_attrs = std::vector<Attribute> ()) + : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), + field_type (std::move (field_type)) + {} + + // Copy constructor with clone + TupleField (TupleField const &other) + : outer_attrs (other.outer_attrs), visibility (other.visibility), + field_type (other.field_type->clone_type ()) + {} + + ~TupleField () = default; + + // Overloaded assignment operator to clone + TupleField &operator= (TupleField const &other) + { + field_type = other.field_type->clone_type (); + visibility = other.visibility; + outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + TupleField (TupleField &&other) = default; + TupleField &operator= (TupleField &&other) = default; + + // Returns whether tuple field is in an error state. + bool is_error () const { return field_type == nullptr; } + + // Creates an error state tuple field. + static TupleField create_error () + { + return TupleField (nullptr, Visibility::create_error ()); + } + + std::string as_string () const; +}; + +// Rust tuple declared using struct keyword HIR node +class TupleStruct : public Struct +{ + std::vector<TupleField> fields; + +public: + std::string as_string () const override; + + // Mega-constructor with all possible fields + TupleStruct (Analysis::NodeMapping mappings, std::vector<TupleField> fields, + Identifier struct_name, + std::vector<std::unique_ptr<GenericParam> > generic_params, + WhereClause where_clause, Visibility vis, + std::vector<Attribute> outer_attrs, Location locus) + : Struct (std::move (mappings), std::move (struct_name), + std::move (generic_params), std::move (where_clause), + std::move (vis), locus, std::move (outer_attrs)), + fields (std::move (fields)) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + TupleStruct *clone_item_impl () const override + { + return new TupleStruct (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual TupleStruct* clone_statement_impl() const override { + return new TupleStruct(*this); + }*/ +}; + +/* An item used in an "enum" tagged union - not abstract: base represents a + * name-only enum */ +class EnumItem +{ + // bool has_attrs; + std::vector<Attribute> outer_attrs; + + Identifier variant_name; + + Location locus; + +public: + virtual ~EnumItem () {} + + // Returns whether enum item has outer attributes. + bool has_outer_attrs () const { return !outer_attrs.empty (); } + + EnumItem (Identifier variant_name, std::vector<Attribute> outer_attrs, + Location locus) + : outer_attrs (std::move (outer_attrs)), + variant_name (std::move (variant_name)), locus (locus) + {} + + // Unique pointer custom clone function + std::unique_ptr<EnumItem> clone_enum_item () const + { + return std::unique_ptr<EnumItem> (clone_enum_item_impl ()); + } + + virtual std::string as_string () const; + + // not pure virtual as not abstract + virtual void accept_vis (HIRVisitor &vis); + +protected: + // Clone function implementation as (not pure) virtual method + virtual EnumItem *clone_enum_item_impl () const + { + return new EnumItem (*this); + } +}; + +// A tuple item used in an "enum" tagged union +class EnumItemTuple : public EnumItem +{ + // bool has_tuple_fields; + std::vector<TupleField> tuple_fields; + +public: + // Returns whether tuple enum item has tuple fields. + bool has_tuple_fields () const { return !tuple_fields.empty (); } + + EnumItemTuple (Identifier variant_name, std::vector<TupleField> tuple_fields, + std::vector<Attribute> outer_attrs, Location locus) + : EnumItem (std::move (variant_name), std::move (outer_attrs), locus), + tuple_fields (std::move (tuple_fields)) + {} + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + EnumItemTuple *clone_enum_item_impl () const override + { + return new EnumItemTuple (*this); + } +}; + +// A struct item used in an "enum" tagged union +class EnumItemStruct : public EnumItem +{ + // bool has_struct_fields; + std::vector<StructField> struct_fields; + +public: + // Returns whether struct enum item has struct fields. + bool has_struct_fields () const { return !struct_fields.empty (); } + + EnumItemStruct (Identifier variant_name, + std::vector<StructField> struct_fields, + std::vector<Attribute> outer_attrs, Location locus) + : EnumItem (std::move (variant_name), std::move (outer_attrs), locus), + struct_fields (std::move (struct_fields)) + {} + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + EnumItemStruct *clone_enum_item_impl () const override + { + return new EnumItemStruct (*this); + } +}; + +// A discriminant (numbered enum) item used in an "enum" tagged union +class EnumItemDiscriminant : public EnumItem +{ + std::unique_ptr<Expr> expression; + +public: + EnumItemDiscriminant (Identifier variant_name, std::unique_ptr<Expr> expr, + std::vector<Attribute> outer_attrs, Location locus) + : EnumItem (std::move (variant_name), std::move (outer_attrs), locus), + expression (std::move (expr)) + {} + + // Copy constructor with clone + EnumItemDiscriminant (EnumItemDiscriminant const &other) + : EnumItem (other), expression (other.expression->clone_expr ()) + {} + + // Overloaded assignment operator to clone + EnumItemDiscriminant &operator= (EnumItemDiscriminant const &other) + { + EnumItem::operator= (other); + expression = other.expression->clone_expr (); + // variant_name = other.variant_name; + // outer_attrs = other.outer_attrs; + + return *this; + } + + // move constructors + EnumItemDiscriminant (EnumItemDiscriminant &&other) = default; + EnumItemDiscriminant &operator= (EnumItemDiscriminant &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + EnumItemDiscriminant *clone_enum_item_impl () const override + { + return new EnumItemDiscriminant (*this); + } +}; + +// HIR node for Rust "enum" - tagged union +class Enum : public VisItem +{ + Identifier enum_name; + + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::vector<std::unique_ptr<EnumItem> > items; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether "enum" has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether "enum" has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + /* Returns whether enum is a "zero-variant" (no possible variant) enum, + * which cannot be instantiated. */ + bool is_zero_variant () const { return items.empty (); } + + // Mega-constructor + Enum (Analysis::NodeMapping mappings, Identifier enum_name, Visibility vis, + std::vector<std::unique_ptr<GenericParam> > generic_params, + WhereClause where_clause, std::vector<std::unique_ptr<EnumItem> > items, + std::vector<Attribute> outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + enum_name (std::move (enum_name)), + generic_params (std::move (generic_params)), + where_clause (std::move (where_clause)), items (std::move (items)), + locus (locus) + {} + + // TODO: constructor with less arguments + + // Copy constructor with vector clone + Enum (Enum const &other) + : VisItem (other), enum_name (other.enum_name), + where_clause (other.where_clause), locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_enum_item ()); + } + + // Overloaded assignment operator with vector clone + Enum &operator= (Enum const &other) + { + VisItem::operator= (other); + enum_name = other.enum_name; + where_clause = other.where_clause; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_enum_item ()); + + return *this; + } + + // Move constructors + Enum (Enum &&other) = default; + Enum &operator= (Enum &&other) = default; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Enum *clone_item_impl () const override { return new Enum (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual Enum* clone_statement_impl() const override { + return new Enum(*this); + }*/ +}; + +// Rust untagged union used for C compat HIR node +class Union : public VisItem +{ + Identifier union_name; + + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::vector<StructField> variants; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether union has generic params. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether union has where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + Union (Analysis::NodeMapping mappings, Identifier union_name, Visibility vis, + std::vector<std::unique_ptr<GenericParam> > generic_params, + WhereClause where_clause, std::vector<StructField> variants, + std::vector<Attribute> outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + union_name (std::move (union_name)), + generic_params (std::move (generic_params)), + where_clause (std::move (where_clause)), variants (std::move (variants)), + locus (locus) + {} + + // copy constructor with vector clone + Union (Union const &other) + : VisItem (other), union_name (other.union_name), + where_clause (other.where_clause), variants (other.variants), + locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // overloaded assignment operator with vector clone + Union &operator= (Union const &other) + { + VisItem::operator= (other); + union_name = other.union_name; + where_clause = other.where_clause; + variants = other.variants; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + Union (Union &&other) = default; + Union &operator= (Union &&other) = default; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Union *clone_item_impl () const override { return new Union (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual Union* clone_statement_impl() const override { + return new Union(*this); + }*/ +}; + +/* "Constant item" HIR node - used for constant, compile-time expressions + * within module scope (like constexpr) */ +class ConstantItem : public VisItem, + public InherentImplItem, + public TraitImplItem +{ + // either has an identifier or "_" - maybe handle in identifier? + // bool identifier_is_underscore; + // if no identifier declared, identifier will be "_" + Identifier identifier; + + std::unique_ptr<Type> type; + std::unique_ptr<Expr> const_expr; + + Location locus; + +public: + std::string as_string () const override; + + ConstantItem (Analysis::NodeMapping mappings, Identifier ident, + Visibility vis, std::unique_ptr<Type> type, + std::unique_ptr<Expr> const_expr, + std::vector<Attribute> outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + identifier (std::move (ident)), type (std::move (type)), + const_expr (std::move (const_expr)), locus (locus) + {} + + ConstantItem (ConstantItem const &other) + : VisItem (other), identifier (other.identifier), + type (other.type->clone_type ()), + const_expr (other.const_expr->clone_expr ()), locus (other.locus) + {} + + // Overload assignment operator to clone + ConstantItem &operator= (ConstantItem const &other) + { + VisItem::operator= (other); + identifier = other.identifier; + type = other.type->clone_type (); + const_expr = other.const_expr->clone_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + ConstantItem (ConstantItem &&other) = default; + ConstantItem &operator= (ConstantItem &&other) = default; + + /* Returns whether constant item is an "unnamed" (wildcard underscore used + * as identifier) constant. */ + bool is_unnamed () const { return identifier == std::string ("_"); } + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ConstantItem *clone_item_impl () const override + { + return new ConstantItem (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + ConstantItem *clone_inherent_impl_item_impl () const override + { + return new ConstantItem (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + ConstantItem *clone_trait_impl_item_impl () const override + { + return new ConstantItem (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual ConstantItem* clone_statement_impl() const override { + return new ConstantItem(*this); + }*/ +}; + +/* Static item HIR node - items within module scope with fixed storage + * duration? */ +class StaticItem : public VisItem +{ + bool has_mut; + Identifier name; + std::unique_ptr<Type> type; + std::unique_ptr<Expr> expr; + Location locus; + +public: + std::string as_string () const override; + + StaticItem (Analysis::NodeMapping mappings, Identifier name, bool is_mut, + std::unique_ptr<Type> type, std::unique_ptr<Expr> expr, + Visibility vis, std::vector<Attribute> outer_attrs, + Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + has_mut (is_mut), name (std::move (name)), type (std::move (type)), + expr (std::move (expr)), locus (locus) + {} + + // Copy constructor with clone + StaticItem (StaticItem const &other) + : VisItem (other), has_mut (other.has_mut), name (other.name), + type (other.type->clone_type ()), expr (other.expr->clone_expr ()), + locus (other.locus) + {} + + // Overloaded assignment operator to clone + StaticItem &operator= (StaticItem const &other) + { + VisItem::operator= (other); + name = other.name; + has_mut = other.has_mut; + type = other.type->clone_type (); + expr = other.expr->clone_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + StaticItem (StaticItem &&other) = default; + StaticItem &operator= (StaticItem &&other) = default; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + StaticItem *clone_item_impl () const override + { + return new StaticItem (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual StaticItem* clone_statement_impl() const override { + return new StaticItem(*this); + }*/ +}; + +// Function declaration in traits +struct TraitFunctionDecl +{ +private: + // TODO: delete and replace with Function decl item? no as no body in this. + FunctionQualifiers qualifiers; + Identifier function_name; + + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + // bool has_params; + // FunctionParams function_params; + std::vector<FunctionParam> function_params; // inlined + + // bool has_return_type; + std::unique_ptr<Type> return_type; + + // bool has_where_clause; + WhereClause where_clause; + + // should this store location info? + +public: + // Returns whether function decl has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether function decl has regular parameters. + bool has_params () const { return !function_params.empty (); } + + // Returns whether function has return type (otherwise is void). + bool has_return_type () const { return return_type != nullptr; } + + // Returns whether function has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + // Mega-constructor + TraitFunctionDecl (Identifier function_name, FunctionQualifiers qualifiers, + std::vector<std::unique_ptr<GenericParam> > generic_params, + std::vector<FunctionParam> function_params, + std::unique_ptr<Type> return_type, + WhereClause where_clause) + : qualifiers (std::move (qualifiers)), + function_name (std::move (function_name)), + generic_params (std::move (generic_params)), + function_params (std::move (function_params)), + return_type (std::move (return_type)), + where_clause (std::move (where_clause)) + {} + + // Copy constructor with clone + TraitFunctionDecl (TraitFunctionDecl const &other) + : qualifiers (other.qualifiers), function_name (other.function_name), + function_params (other.function_params), + return_type (other.return_type->clone_type ()), + where_clause (other.where_clause) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + ~TraitFunctionDecl () = default; + + // Overloaded assignment operator with clone + TraitFunctionDecl &operator= (TraitFunctionDecl const &other) + { + function_name = other.function_name; + qualifiers = other.qualifiers; + function_params = other.function_params; + return_type = other.return_type->clone_type (); + where_clause = other.where_clause; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + TraitFunctionDecl (TraitFunctionDecl &&other) = default; + TraitFunctionDecl &operator= (TraitFunctionDecl &&other) = default; + + std::string as_string () const; +}; + +// Actual trait item function declaration within traits +class TraitItemFunc : public TraitItem +{ + std::vector<Attribute> outer_attrs; + TraitFunctionDecl decl; + std::unique_ptr<BlockExpr> block_expr; + Location locus; + +public: + // Returns whether function has a definition or is just a declaration. + bool has_definition () const { return block_expr != nullptr; } + + TraitItemFunc (TraitFunctionDecl decl, std::unique_ptr<BlockExpr> block_expr, + std::vector<Attribute> outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), decl (std::move (decl)), + block_expr (std::move (block_expr)), locus (locus) + {} + + // Copy constructor with clone + TraitItemFunc (TraitItemFunc const &other) + : outer_attrs (other.outer_attrs), decl (other.decl), locus (other.locus) + { + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + } + + // Overloaded assignment operator to clone + TraitItemFunc &operator= (TraitItemFunc const &other) + { + TraitItem::operator= (other); + outer_attrs = other.outer_attrs; + decl = other.decl; + locus = other.locus; + if (other.block_expr != nullptr) + block_expr = other.block_expr->clone_block_expr (); + + return *this; + } + + // move constructors + TraitItemFunc (TraitItemFunc &&other) = default; + TraitItemFunc &operator= (TraitItemFunc &&other) = default; + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + TraitItemFunc *clone_trait_item_impl () const override + { + return new TraitItemFunc (*this); + } +}; + +// Method declaration within traits +struct TraitMethodDecl +{ +private: + // TODO: delete and replace with Function decl item? no as no body. + FunctionQualifiers qualifiers; + Identifier function_name; + + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + SelfParam self_param; + + // bool has_params; + // FunctionParams function_params; + std::vector<FunctionParam> function_params; // inlined + + // bool has_return_type; + std::unique_ptr<Type> return_type; + + // bool has_where_clause; + WhereClause where_clause; + + // should this store location info? + +public: + // Returns whether method decl has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether method decl has regular parameters. + bool has_params () const { return !function_params.empty (); } + + // Returns whether method has return type (otherwise is void). + bool has_return_type () const { return return_type != nullptr; } + + // Returns whether method has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + // Mega-constructor + TraitMethodDecl (Identifier function_name, FunctionQualifiers qualifiers, + std::vector<std::unique_ptr<GenericParam> > generic_params, + SelfParam self_param, + std::vector<FunctionParam> function_params, + std::unique_ptr<Type> return_type, WhereClause where_clause) + : qualifiers (std::move (qualifiers)), + function_name (std::move (function_name)), + generic_params (std::move (generic_params)), + self_param (std::move (self_param)), + function_params (std::move (function_params)), + return_type (std::move (return_type)), + where_clause (std::move (where_clause)) + {} + + // Copy constructor with clone + TraitMethodDecl (TraitMethodDecl const &other) + : qualifiers (other.qualifiers), function_name (other.function_name), + self_param (other.self_param), function_params (other.function_params), + return_type (other.return_type->clone_type ()), + where_clause (other.where_clause) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + ~TraitMethodDecl () = default; + + // Overloaded assignment operator with clone + TraitMethodDecl &operator= (TraitMethodDecl const &other) + { + function_name = other.function_name; + qualifiers = other.qualifiers; + self_param = other.self_param; + function_params = other.function_params; + return_type = other.return_type->clone_type (); + where_clause = other.where_clause; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + TraitMethodDecl (TraitMethodDecl &&other) = default; + TraitMethodDecl &operator= (TraitMethodDecl &&other) = default; + + std::string as_string () const; +}; + +// Actual trait item method declaration within traits +class TraitItemMethod : public TraitItem +{ + std::vector<Attribute> outer_attrs; + TraitMethodDecl decl; + std::unique_ptr<BlockExpr> block_expr; + Location locus; + +public: + // Returns whether method has a definition or is just a declaration. + bool has_definition () const { return block_expr != nullptr; } + + TraitItemMethod (TraitMethodDecl decl, std::unique_ptr<BlockExpr> block_expr, + std::vector<Attribute> outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), decl (std::move (decl)), + block_expr (std::move (block_expr)), locus (locus) + {} + + // Copy constructor with clone + TraitItemMethod (TraitItemMethod const &other) + : outer_attrs (other.outer_attrs), decl (other.decl), + block_expr (other.block_expr->clone_block_expr ()), locus (other.locus) + {} + + // Overloaded assignment operator to clone + TraitItemMethod &operator= (TraitItemMethod const &other) + { + TraitItem::operator= (other); + outer_attrs = other.outer_attrs; + decl = other.decl; + block_expr = other.block_expr->clone_block_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + TraitItemMethod (TraitItemMethod &&other) = default; + TraitItemMethod &operator= (TraitItemMethod &&other) = default; + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + TraitItemMethod *clone_trait_item_impl () const override + { + return new TraitItemMethod (*this); + } +}; + +// Constant item within traits +class TraitItemConst : public TraitItem +{ + std::vector<Attribute> outer_attrs; + Identifier name; + std::unique_ptr<Type> type; + + // bool has_expression; + std::unique_ptr<Expr> expr; + + Location locus; + +public: + // Whether the constant item has an associated expression. + bool has_expression () const { return expr != nullptr; } + + TraitItemConst (Identifier name, std::unique_ptr<Type> type, + std::unique_ptr<Expr> expr, + std::vector<Attribute> outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), name (std::move (name)), + type (std::move (type)), expr (std::move (expr)), locus (locus) + {} + + // Copy constructor with clones + TraitItemConst (TraitItemConst const &other) + : outer_attrs (other.outer_attrs), name (other.name), + type (other.type->clone_type ()), expr (other.expr->clone_expr ()), + locus (other.locus) + {} + + // Overloaded assignment operator to clone + TraitItemConst &operator= (TraitItemConst const &other) + { + TraitItem::operator= (other); + outer_attrs = other.outer_attrs; + name = other.name; + type = other.type->clone_type (); + expr = other.expr->clone_expr (); + locus = other.locus; + + return *this; + } + + // move constructors + TraitItemConst (TraitItemConst &&other) = default; + TraitItemConst &operator= (TraitItemConst &&other) = default; + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + TraitItemConst *clone_trait_item_impl () const override + { + return new TraitItemConst (*this); + } +}; + +// Type items within traits +class TraitItemType : public TraitItem +{ + std::vector<Attribute> outer_attrs; + + Identifier name; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + std::vector<std::unique_ptr<TypeParamBound> > + type_param_bounds; // inlined form + + Location locus; + +public: + // Returns whether trait item type has type param bounds. + bool has_type_param_bounds () const { return !type_param_bounds.empty (); } + + TraitItemType ( + Identifier name, + std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, + std::vector<Attribute> outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), name (std::move (name)), + type_param_bounds (std::move (type_param_bounds)), locus (locus) + {} + + // Copy constructor with vector clone + TraitItemType (TraitItemType const &other) + : outer_attrs (other.outer_attrs), name (other.name), locus (other.locus) + { + 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 with vector clone + TraitItemType &operator= (TraitItemType const &other) + { + TraitItem::operator= (other); + outer_attrs = other.outer_attrs; + name = other.name; + locus = other.locus; + + 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; + } + + // default move constructors + TraitItemType (TraitItemType &&other) = default; + TraitItemType &operator= (TraitItemType &&other) = default; + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Clone function implementation as (not pure) virtual method + TraitItemType *clone_trait_item_impl () const override + { + return new TraitItemType (*this); + } +}; + +// Rust trait item declaration HIR node +class Trait : public VisItem +{ + bool has_unsafe; + + Identifier name; + + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + std::vector<std::unique_ptr<TypeParamBound> > + type_param_bounds; // inlined form + + // bool has_where_clause; + WhereClause where_clause; + + // bool has_trait_items; + std::vector<std::unique_ptr<TraitItem> > trait_items; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether trait has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether trait has type parameter bounds. + bool has_type_param_bounds () const { return !type_param_bounds.empty (); } + + // Returns whether trait has where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + // Returns whether trait has trait items. + bool has_trait_items () const { return !trait_items.empty (); } + + // Mega-constructor + Trait (Analysis::NodeMapping mappings, Identifier name, bool is_unsafe, + std::vector<std::unique_ptr<GenericParam> > generic_params, + std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, + WhereClause where_clause, + std::vector<std::unique_ptr<TraitItem> > trait_items, Visibility vis, + std::vector<Attribute> outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + has_unsafe (is_unsafe), name (std::move (name)), + generic_params (std::move (generic_params)), + type_param_bounds (std::move (type_param_bounds)), + where_clause (std::move (where_clause)), + trait_items (std::move (trait_items)), locus (locus) + {} + + // Copy constructor with vector clone + Trait (Trait const &other) + : VisItem (other), has_unsafe (other.has_unsafe), name (other.name), + where_clause (other.where_clause), locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + 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 ()); + + trait_items.reserve (other.trait_items.size ()); + for (const auto &e : other.trait_items) + trait_items.push_back (e->clone_trait_item ()); + } + + // Overloaded assignment operator with vector clone + Trait &operator= (Trait const &other) + { + VisItem::operator= (other); + name = other.name; + has_unsafe = other.has_unsafe; + where_clause = other.where_clause; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + 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 ()); + + trait_items.reserve (other.trait_items.size ()); + for (const auto &e : other.trait_items) + trait_items.push_back (e->clone_trait_item ()); + + return *this; + } + + // default move constructors + Trait (Trait &&other) = default; + Trait &operator= (Trait &&other) = default; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + Trait *clone_item_impl () const override { return new Trait (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual Trait* clone_statement_impl() const override { + return new Trait(*this); + }*/ +}; + +// Implementation item declaration HIR node - abstract base class +class Impl : public VisItem +{ + // must be protected to allow subclasses to access them properly +protected: + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + std::unique_ptr<Type> trait_type; + + // bool has_where_clause; + WhereClause where_clause; + + // bool has_inner_attrs; + std::vector<Attribute> inner_attrs; + +private: + // doesn't really need to be protected as write access probably not needed + Location locus; + +public: + // Returns whether impl has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether impl has where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + // Returns whether impl has inner attributes. + bool has_inner_attrs () const { return !inner_attrs.empty (); } + + Location get_locus () const { return locus; } + +protected: + // Mega-constructor + Impl (Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<GenericParam> > generic_params, + std::unique_ptr<Type> trait_type, WhereClause where_clause, + Visibility vis, std::vector<Attribute> inner_attrs, + std::vector<Attribute> outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + generic_params (std::move (generic_params)), + trait_type (std::move (trait_type)), + where_clause (std::move (where_clause)), + inner_attrs (std::move (inner_attrs)), locus (locus) + {} + + // Copy constructor + Impl (Impl const &other) + : VisItem (other), trait_type (other.trait_type->clone_type ()), + where_clause (other.where_clause), inner_attrs (other.inner_attrs), + locus (other.locus) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Assignment operator overload with cloning + Impl &operator= (Impl const &other) + { + VisItem::operator= (other); + trait_type = other.trait_type->clone_type (); + where_clause = other.where_clause; + inner_attrs = other.inner_attrs; + locus = other.locus; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + Impl (Impl &&other) = default; + Impl &operator= (Impl &&other) = default; +}; + +// Regular "impl foo" impl block declaration HIR node +class InherentImpl : public Impl +{ + // bool has_impl_items; + std::vector<std::unique_ptr<InherentImplItem> > impl_items; + +public: + std::string as_string () const override; + + // Returns whether inherent impl block has inherent impl items. + bool has_impl_items () const { return !impl_items.empty (); } + + // Mega-constructor + InherentImpl (Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<InherentImplItem> > impl_items, + std::vector<std::unique_ptr<GenericParam> > generic_params, + std::unique_ptr<Type> trait_type, WhereClause where_clause, + Visibility vis, std::vector<Attribute> inner_attrs, + std::vector<Attribute> outer_attrs, Location locus) + : Impl (std::move (mappings), std::move (generic_params), + std::move (trait_type), std::move (where_clause), std::move (vis), + std::move (inner_attrs), std::move (outer_attrs), locus), + impl_items (std::move (impl_items)) + {} + + // Copy constructor with vector clone + InherentImpl (InherentImpl const &other) : Impl (other) + { + impl_items.reserve (other.impl_items.size ()); + for (const auto &e : other.impl_items) + impl_items.push_back (e->clone_inherent_impl_item ()); + } + + // Overloaded assignment operator with vector clone + InherentImpl &operator= (InherentImpl const &other) + { + Impl::operator= (other); + + impl_items.reserve (other.impl_items.size ()); + for (const auto &e : other.impl_items) + impl_items.push_back (e->clone_inherent_impl_item ()); + + return *this; + } + + // default move constructors + InherentImpl (InherentImpl &&other) = default; + InherentImpl &operator= (InherentImpl &&other) = default; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + InherentImpl *clone_item_impl () const override + { + return new InherentImpl (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual InherentImpl* clone_statement_impl() const override { + return new InherentImpl(*this); + }*/ +}; + +// The "impl footrait for foo" impl block declaration HIR node +class TraitImpl : public Impl +{ + bool has_unsafe; + bool has_exclam; + TypePath trait_path; + + // bool has_impl_items; + std::vector<std::unique_ptr<TraitImplItem> > impl_items; + +public: + std::string as_string () const override; + + // Returns whether trait impl has impl items. + bool has_impl_items () const { return !impl_items.empty (); } + + // Mega-constructor + TraitImpl (Analysis::NodeMapping mappings, TypePath trait_path, + bool is_unsafe, bool has_exclam, + std::vector<std::unique_ptr<TraitImplItem> > impl_items, + std::vector<std::unique_ptr<GenericParam> > generic_params, + std::unique_ptr<Type> trait_type, WhereClause where_clause, + Visibility vis, std::vector<Attribute> inner_attrs, + std::vector<Attribute> outer_attrs, Location locus) + : Impl (std::move (mappings), std::move (generic_params), + std::move (trait_type), std::move (where_clause), std::move (vis), + std::move (inner_attrs), std::move (outer_attrs), locus), + has_unsafe (is_unsafe), has_exclam (has_exclam), + trait_path (std::move (trait_path)), impl_items (std::move (impl_items)) + {} + + // TODO: constructors with less params + + // Copy constructor with vector clone + TraitImpl (TraitImpl const &other) + : Impl (other), has_unsafe (other.has_unsafe), + has_exclam (other.has_exclam), trait_path (other.trait_path) + { + impl_items.reserve (other.impl_items.size ()); + for (const auto &e : other.impl_items) + impl_items.push_back (e->clone_trait_impl_item ()); + } + + // Overloaded assignment operator with vector clone + TraitImpl &operator= (TraitImpl const &other) + { + Impl::operator= (other); + trait_path = other.trait_path; + has_unsafe = other.has_unsafe; + has_exclam = other.has_exclam; + + impl_items.reserve (other.impl_items.size ()); + for (const auto &e : other.impl_items) + impl_items.push_back (e->clone_trait_impl_item ()); + + return *this; + } + + // move constructors + TraitImpl (TraitImpl &&other) = default; + TraitImpl &operator= (TraitImpl &&other) = default; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + TraitImpl *clone_item_impl () const override { return new TraitImpl (*this); } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual TraitImpl* clone_statement_impl() const override { + return new TraitImpl(*this); + }*/ +}; + +// Abstract base class for an item used inside an extern block +class ExternalItem +{ + // bool has_outer_attrs; + std::vector<Attribute> outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier item_name; + Location locus; + +public: + virtual ~ExternalItem () {} + + // Returns whether item has outer attributes. + bool has_outer_attrs () const { return !outer_attrs.empty (); } + + // Returns whether item has non-default visibility. + bool has_visibility () const { return !visibility.is_error (); } + + // Unique pointer custom clone function + std::unique_ptr<ExternalItem> clone_external_item () const + { + return std::unique_ptr<ExternalItem> (clone_external_item_impl ()); + } + + virtual std::string as_string () const; + + Location get_locus () const { return locus; } + + virtual void accept_vis (HIRVisitor &vis) = 0; + +protected: + ExternalItem (Identifier item_name, Visibility vis, + std::vector<Attribute> outer_attrs, Location locus) + : outer_attrs (std::move (outer_attrs)), visibility (std::move (vis)), + item_name (std::move (item_name)), locus (locus) + {} + + // Copy constructor + ExternalItem (ExternalItem const &other) + : outer_attrs (other.outer_attrs), visibility (other.visibility), + item_name (other.item_name), locus (other.locus) + {} + + // Overloaded assignment operator to clone + ExternalItem &operator= (ExternalItem const &other) + { + item_name = other.item_name; + visibility = other.visibility; + outer_attrs = other.outer_attrs; + locus = other.locus; + + return *this; + } + + // move constructors + ExternalItem (ExternalItem &&other) = default; + ExternalItem &operator= (ExternalItem &&other) = default; + + // Clone function implementation as pure virtual method + virtual ExternalItem *clone_external_item_impl () const = 0; + + // possibly make this public if required + std::string get_item_name () const { return item_name; } +}; + +// A static item used in an extern block +class ExternalStaticItem : public ExternalItem +{ + bool has_mut; + std::unique_ptr<Type> item_type; + +public: + ExternalStaticItem (Identifier item_name, std::unique_ptr<Type> item_type, + bool is_mut, Visibility vis, + std::vector<Attribute> outer_attrs, Location locus) + : ExternalItem (std::move (item_name), std::move (vis), + std::move (outer_attrs), locus), + has_mut (is_mut), item_type (std::move (item_type)) + {} + + // Copy constructor + ExternalStaticItem (ExternalStaticItem const &other) + : ExternalItem (other), has_mut (other.has_mut), + item_type (other.item_type->clone_type ()) + {} + + // Overloaded assignment operator to clone + ExternalStaticItem &operator= (ExternalStaticItem const &other) + { + ExternalItem::operator= (other); + item_type = other.item_type->clone_type (); + has_mut = other.has_mut; + + return *this; + } + + // move constructors + ExternalStaticItem (ExternalStaticItem &&other) = default; + ExternalStaticItem &operator= (ExternalStaticItem &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ExternalStaticItem *clone_external_item_impl () const override + { + return new ExternalStaticItem (*this); + } +}; + +// A named function parameter used in external functions +struct NamedFunctionParam +{ +private: + // bool has_name; // otherwise is _ + Identifier name; // TODO: handle wildcard in identifier? + + std::unique_ptr<Type> param_type; + + // TODO: should this store location data? + +public: + // Returns whether the named function parameter has a name (i.e. name is not + // '_'). + bool has_name () const { return name != "_"; } + + // Returns whether the named function parameter is in an error state. + bool is_error () const + { + // also if identifier is "" but that is probably more costly to compute + return param_type == nullptr; + } + + // Creates an error state named function parameter. + static NamedFunctionParam create_error () + { + return NamedFunctionParam ("", nullptr); + } + + NamedFunctionParam (Identifier name, std::unique_ptr<Type> param_type) + : name (std::move (name)), param_type (std::move (param_type)) + {} + + // Copy constructor + NamedFunctionParam (NamedFunctionParam const &other) + : name (other.name), param_type (other.param_type->clone_type ()) + {} + + ~NamedFunctionParam () = default; + + // Overloaded assignment operator to clone + NamedFunctionParam &operator= (NamedFunctionParam const &other) + { + name = other.name; + param_type = other.param_type->clone_type (); + // has_name = other.has_name; + + return *this; + } + + // move constructors + NamedFunctionParam (NamedFunctionParam &&other) = default; + NamedFunctionParam &operator= (NamedFunctionParam &&other) = default; + + std::string as_string () const; +}; + +// A function item used in an extern block +class ExternalFunctionItem : public ExternalItem +{ + // bool has_generics; + // Generics generic_params; + std::vector<std::unique_ptr<GenericParam> > generic_params; // inlined + + // bool has_return_type; + // FunctionReturnType return_type; + std::unique_ptr<Type> return_type; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::vector<NamedFunctionParam> function_params; + bool has_variadics; + +public: + // Returns whether item has generic parameters. + bool has_generics () const { return !generic_params.empty (); } + + // Returns whether item has a return type (otherwise void). + bool has_return_type () const { return return_type != nullptr; } + + // Returns whether item has a where clause. + bool has_where_clause () const { return !where_clause.is_empty (); } + + ExternalFunctionItem ( + Identifier item_name, + std::vector<std::unique_ptr<GenericParam> > generic_params, + std::unique_ptr<Type> return_type, WhereClause where_clause, + std::vector<NamedFunctionParam> function_params, bool has_variadics, + Visibility vis, std::vector<Attribute> outer_attrs, Location locus) + : ExternalItem (std::move (item_name), std::move (vis), + std::move (outer_attrs), locus), + generic_params (std::move (generic_params)), + return_type (std::move (return_type)), + where_clause (std::move (where_clause)), + function_params (std::move (function_params)), + has_variadics (has_variadics) + {} + + // Copy constructor with clone + ExternalFunctionItem (ExternalFunctionItem const &other) + : ExternalItem (other), return_type (other.return_type->clone_type ()), + where_clause (other.where_clause), + function_params (other.function_params), + has_variadics (other.has_variadics) + { + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + } + + // Overloaded assignment operator with clone + ExternalFunctionItem &operator= (ExternalFunctionItem const &other) + { + ExternalItem::operator= (other); + return_type = other.return_type->clone_type (); + where_clause = other.where_clause; + function_params = other.function_params; + has_variadics = other.has_variadics; + + generic_params.reserve (other.generic_params.size ()); + for (const auto &e : other.generic_params) + generic_params.push_back (e->clone_generic_param ()); + + return *this; + } + + // move constructors + ExternalFunctionItem (ExternalFunctionItem &&other) = default; + ExternalFunctionItem &operator= (ExternalFunctionItem &&other) = default; + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ExternalFunctionItem *clone_external_item_impl () const override + { + return new ExternalFunctionItem (*this); + } +}; + +// An extern block HIR node +class ExternBlock : public VisItem +{ + // bool has_abi; + std::string abi; + + // bool has_inner_attrs; + std::vector<Attribute> inner_attrs; + + // bool has_extern_items; + std::vector<std::unique_ptr<ExternalItem> > extern_items; + + Location locus; + +public: + std::string as_string () const override; + + // Returns whether extern block has inner attributes. + bool has_inner_attrs () const { return !inner_attrs.empty (); } + + // Returns whether extern block has extern items. + bool has_extern_items () const { return !extern_items.empty (); } + + // Returns whether extern block has ABI name. + bool has_abi () const { return !abi.empty (); } + + ExternBlock (Analysis::NodeMapping mappings, std::string abi, + std::vector<std::unique_ptr<ExternalItem> > extern_items, + Visibility vis, std::vector<Attribute> inner_attrs, + std::vector<Attribute> outer_attrs, Location locus) + : VisItem (std::move (mappings), std::move (vis), std::move (outer_attrs)), + abi (std::move (abi)), inner_attrs (std::move (inner_attrs)), + extern_items (std::move (extern_items)), locus (locus) + {} + + // Copy constructor with vector clone + ExternBlock (ExternBlock const &other) + : VisItem (other), abi (other.abi), inner_attrs (other.inner_attrs), + locus (other.locus) + { + extern_items.reserve (other.extern_items.size ()); + for (const auto &e : other.extern_items) + extern_items.push_back (e->clone_external_item ()); + } + + // Overloaded assignment operator with vector clone + ExternBlock &operator= (ExternBlock const &other) + { + VisItem::operator= (other); + abi = other.abi; + inner_attrs = other.inner_attrs; + locus = other.locus; + + extern_items.reserve (other.extern_items.size ()); + for (const auto &e : other.extern_items) + extern_items.push_back (e->clone_external_item ()); + + return *this; + } + + // move constructors + ExternBlock (ExternBlock &&other) = default; + ExternBlock &operator= (ExternBlock &&other) = default; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object + * rather than base */ + ExternBlock *clone_item_impl () const override + { + return new ExternBlock (*this); + } + + /* Use covariance to implement clone function as returning this object + * rather than base */ + /*virtual ExternBlock* clone_statement_impl() const override { + return new ExternBlock(*this); + }*/ +}; + +// Replaced with forward decls - defined in "rust-macro.h" +class MacroItem; +class MacroInvocationSemi; +class MacroRulesDefinition; +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-macro.h b/gcc/rust/hir/tree/rust-hir-macro.h new file mode 100644 index 0000000..84b4914 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-macro.h @@ -0,0 +1,628 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_MACRO_H +#define RUST_HIR_MACRO_H + +#include "rust-hir.h" + +namespace Rust { +namespace HIR { +// 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. + 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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<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. + 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) + : op (other.op), sep (other.sep->clone_token ()) + { + matches.reserve (other.matches.size ()); + for (const auto &e : other.matches) + matches.push_back (e->clone_macro_match ()); + } + + // Overloaded assignment operator to clone + MacroMatchRepetition &operator= (MacroMatchRepetition const &other) + { + op = other.op; + sep = other.sep->clone_token (); + + 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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<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) + { + 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; + + 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. + bool is_error () const { return is_invalid; } + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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. + 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 HIR 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 override; + + MacroRulesDefinition (Analysis::NodeMapping mappings, Identifier rule_name, + DelimType delim_type, std::vector<MacroRule> rules, + std::vector<Attribute> outer_attrs, Location locus) + : MacroItem (std::move (mappings), std::move (outer_attrs)), + rule_name (std::move (rule_name)), delim_type (delim_type), + rules (std::move (rules)), locus (locus) + {} + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + MacroRulesDefinition *clone_item_impl () const override + { + return new MacroRulesDefinition (*this); + } +}; + +/* HIR 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 override; + + MacroInvocation (Analysis::NodeMapping mappings, SimplePath path, + DelimTokenTree token_tree, + std::vector<Attribute> outer_attrs, Location locus) + : TypeNoBounds (mappings), + ExprWithoutBlock (std::move (mappings), 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + MacroInvocation *clone_pattern_impl () const override + { + return new MacroInvocation (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MacroInvocation *clone_expr_impl () const override + { + return new MacroInvocation (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + MacroInvocation *clone_type_impl () const override + { + return new MacroInvocation (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 (); } + + void accept_vis (HIRVisitor &vis) override; + + // HACK: used to simplify parsing - returns non-empty only in this case + SimplePath to_path_item () const override + { + // this should copy construct - TODO ensure it does + return path; + } + + Attribute to_attribute () const override; + +protected: + // Use covariance to implement clone function as returning this type + 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) + { + seq.reserve (other.seq.size ()); + for (const auto &e : other.seq) + seq.push_back (e->clone_meta_item_inner ()); + } + + // overloaded assignment operator with vector clone + MetaItemSeq &operator= (const MetaItemSeq &other) + { + MetaItem::operator= (other); + path = other.path; + + 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; + + void accept_vis (HIRVisitor &vis) override; + + Attribute to_attribute () const override; + +protected: + // Use covariance to implement clone function as returning this type + 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; } + + void accept_vis (HIRVisitor &vis) override; + + Attribute to_attribute () const override; + +protected: + // Use covariance to implement clone function as returning this type + 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; } + + void accept_vis (HIRVisitor &vis) override; + + // HACK: used to simplify parsing - creates a copy of this + std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const override + { + return std::unique_ptr<MetaNameValueStr> (clone_meta_item_inner_impl ()); + } + + Attribute to_attribute () const override; + +protected: + // Use covariance to implement clone function as returning this type + 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; + + void accept_vis (HIRVisitor &vis) override; + + Attribute to_attribute () const override; + +protected: + // Use covariance to implement clone function as returning this type + 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; + + void accept_vis (HIRVisitor &vis) override; + + Attribute to_attribute () const override; + +protected: + // Use covariance to implement clone function as returning this type + 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 HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h new file mode 100644 index 0000000..1bba506 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -0,0 +1,845 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_PATH_H +#define RUST_HIR_PATH_H + +#include "rust-hir.h" + +#include <string> +#include <vector> + +namespace Rust { +namespace HIR { + +// 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. + 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; + std::unique_ptr<Type> type; + + Location locus; + +public: + // Returns whether binding is in an error state. + bool is_error () const + { + return type == nullptr; + // and also identifier is empty, but cheaper computation + } + + // Creates an error state generic args binding. + static GenericArgsBinding create_error () + { + return GenericArgsBinding ("", nullptr); + } + + // 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<std::unique_ptr<Type> > type_args; + std::vector<GenericArgsBinding> binding_args; + Location locus; + +public: + // Returns true if there are any generic arguments + 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) + { + 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; + + 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 + 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. + 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; + + Location get_locus () const { return locus; } +}; + +// HIR 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. + 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). */ + bool is_single_segment () const { return segments.size () == 1; } + + std::string as_string () const override; + + void iterate_path_segments (std::function<bool (PathExprSegment &)> cb) + { + for (auto it = segments.begin (); it != segments.end (); it++) + { + if (!cb (*it)) + return; + } + } +}; + +/* HIR 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 override; + + // Constructor + PathInExpression (Analysis::NodeMapping mappings, + 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 (mappings), 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 (Analysis::NodeMapping::get_error (), + std::vector<PathExprSegment> ()); + } + + // Returns whether path in expression is in an error state. + bool is_error () const { return !has_segments (); } + + /* Converts PathInExpression to SimplePath if possible (i.e. no generic + * arguments). Otherwise returns an empty SimplePath. */ + SimplePath as_simple_path () const + { + /* 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 (); } + + void accept_vis (HIRVisitor &vis) override; + + bool opening_scope_resolution () { return has_opening_scope_resolution; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + PathInExpression *clone_pattern_impl () const override + { + return new PathInExpression (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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. */ + 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; } + + Location get_locus () const { return locus; } + + // not pure virtual as class not abstract + virtual void accept_vis (HIRVisitor &vis); +}; + +// Segment used in type path with generic args +class TypePathSegmentGeneric : public TypePathSegment +{ + GenericArgs generic_args; + +public: + bool has_generic_args () const { return generic_args.has_generic_args (); } + + bool is_ident_only () const override { 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Use covariance to override base class method + 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;*/ + // inlined from TypePathFnInputs + std::vector<std::unique_ptr<Type> > inputs; + + // bool has_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. + bool has_return_type () const { return return_type != nullptr; } + + // Returns whether the function has inputs. + bool has_inputs () const { return !inputs.empty (); } + + // Returns whether function is in an error state. + 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 = nullptr) + : 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 = nullptr) + : inputs (std::move (inputs)), return_type (std::move (type)), + is_invalid (false) + {} + + // Copy constructor with clone + TypePathFunction (TypePathFunction const &other) + : return_type (other.return_type->clone_type ()), + is_invalid (other.is_invalid) + { + 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) + { + return_type = other.return_type->clone_type (); + is_invalid = other.is_invalid; + + 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 override; + + bool is_ident_only () const override { return false; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + // Use covariance to override base class method + TypePathSegmentFunction *clone_type_path_segment_impl () const override + { + return new TypePathSegmentFunction (*this); + } +}; + +// Path used inside types +class TypePath : public TypeNoBounds +{ +public: + 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 */ + TypePath *clone_type_impl () const override { return new TypePath (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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) */ + bool has_opening_scope_resolution_op () const + { + return has_opening_scope_resolution; + } + + // Returns whether the TypePath is in an invalid state. + bool is_error () const { return segments.empty (); } + + // Creates an error state TypePath. + static TypePath create_error () + { + return TypePath (Analysis::NodeMapping::get_error (), + std::vector<std::unique_ptr<TypePathSegment> > (), + Location ()); + } + + // Constructor + TypePath (Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<TypePathSegment> > segments, + Location locus, bool has_opening_scope_resolution = false) + : TypeNoBounds (mappings), + has_opening_scope_resolution (has_opening_scope_resolution), + segments (std::move (segments)), locus (locus) + {} + + // Copy constructor with vector clone + TypePath (TypePath const &other) + : TypeNoBounds (other.mappings), + has_opening_scope_resolution (other.has_opening_scope_resolution), + locus (other.locus) + { + 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; + mappings = other.mappings; + + 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 override; + + /* 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. + TraitBound *to_trait_bound (bool in_parens) const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + + size_t get_num_segments () const { return segments.size (); } + + void iterate_segments (std::function<bool (TypePathSegment *)> cb) + { + for (auto it = segments.begin (); it != segments.end (); it++) + { + if (!cb ((*it).get ())) + return; + } + } +}; + +struct QualifiedPathType +{ +private: + 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. + bool has_as_clause () const { return !trait_path.is_error (); } + + // Returns whether the qualified path type is in an error state. + bool is_error () const { return type_to_invoke_on == nullptr; } + + // Creates an error state qualified path type. + static QualifiedPathType create_error () + { + return QualifiedPathType (nullptr); + } + + std::string as_string () const; + + Location get_locus () const { return locus; } +}; + +/* HIR 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 override; + + QualifiedPathInExpression (Analysis::NodeMapping mappings, + 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 (mappings), 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 */ + + // Returns whether qualified path in expression is in an error state. + bool is_error () const { return path_type.is_error (); } + + // Creates an error qualified path in expression. + static QualifiedPathInExpression create_error () + { + return QualifiedPathInExpression (Analysis::NodeMapping::get_error (), + QualifiedPathType::create_error (), + std::vector<PathExprSegment> ()); + } + + Location get_locus () const { return locus; } + Location get_locus_slow () const override { return get_locus (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + QualifiedPathInExpression *clone_pattern_impl () const override + { + return new QualifiedPathInExpression (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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<std::unique_ptr<TypePathSegment> > segments; + Location locus; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + QualifiedPathInType *clone_type_impl () const override + { + return new QualifiedPathInType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + QualifiedPathInType *clone_type_no_bounds_impl () const override + { + return new QualifiedPathInType (*this); + } + +public: + QualifiedPathInType ( + Analysis::NodeMapping mappings, QualifiedPathType qual_path_type, + std::vector<std::unique_ptr<TypePathSegment> > path_segments, + Location locus = Location ()) + : TypeNoBounds (mappings), 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) + : TypeNoBounds (mappings), path_type (other.path_type), locus (other.locus) + { + 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; + mappings = other.mappings; + + 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; + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; +}; +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-pattern.h b/gcc/rust/hir/tree/rust-hir-pattern.h new file mode 100644 index 0000000..3ff13d2 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-pattern.h @@ -0,0 +1,1162 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_PATTERN_H +#define RUST_HIR_PATTERN_H + +#include "rust-hir.h" + +namespace Rust { +namespace HIR { +// Literal pattern HIR 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 */ + // TODO: 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 override; + + // 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; } + + void accept_vis (HIRVisitor &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 HIR node (bind value matched to a variable) +class IdentifierPattern : public Pattern +{ +public: + Identifier variable_ident; + bool is_ref; + bool is_mut; + + // bool has_pattern; + std::unique_ptr<Pattern> to_bind; + + Location locus; + + std::string as_string () const; + + // Returns whether the IdentifierPattern has a pattern to bind. + bool has_pattern_to_bind () const { return to_bind != nullptr; } + + // Constructor + IdentifierPattern (Identifier ident, Location locus, bool is_ref = false, + bool is_mut = false, + std::unique_ptr<Pattern> to_bind = nullptr) + : 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 != nullptr) + to_bind = other.to_bind->clone_pattern (); + } + + // 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 != nullptr) + 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; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + IdentifierPattern *clone_pattern_impl () const override + { + return new IdentifierPattern (*this); + } +}; + +// HIR node for using the '_' wildcard "match any value" pattern +class WildcardPattern : public Pattern +{ + Location locus; + +public: + std::string as_string () const override { return std::string (1, '_'); } + + WildcardPattern (Location locus) : locus (locus) {} + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + WildcardPattern *clone_pattern_impl () const override + { + return new WildcardPattern (*this); + } +}; + +// Base range pattern bound (lower or upper limit) - abstract +class RangePatternBound +{ +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 (HIRVisitor &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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 override { return path.as_string (); } + + Location get_locus () const { return path.get_locus (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 override { return path.as_string (); } + + Location get_locus () const { return path.get_locus (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePatternBoundQualPath *clone_range_pattern_bound_impl () const override + { + return new RangePatternBoundQualPath (*this); + } +}; + +// HIR node for matching within a certain range (range pattern) +class RangePattern : public Pattern +{ + std::unique_ptr<RangePatternBound> lower; + std::unique_ptr<RangePatternBound> upper; + + bool has_ellipsis_syntax; + + /* 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 override; + + // 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) + {} + + // 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; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RangePattern *clone_pattern_impl () const override + { + return new RangePattern (*this); + } +}; + +// HIR node for pattern based on dereferencing the pointers given +class ReferencePattern : public Pattern +{ + bool has_two_amps; + bool is_mut; + std::unique_ptr<Pattern> pattern; + Location locus; + +public: + std::string as_string () const override; + + 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) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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; + 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 (HIRVisitor &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; + std::unique_ptr<Pattern> tuple_pattern; + +public: + 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 ()) + {} + + // 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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; + std::unique_ptr<Pattern> ident_pattern; + +public: + 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 ()) + {} + + // 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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<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 + bool has_struct_pattern_fields () const { return !fields.empty (); } + + /* Returns whether the struct pattern elements is entirely empty (no fields, + * no etc). */ + 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) + { + 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; + + 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 HIR 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 override; + + // 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). */ + bool has_struct_pattern_elems () const { return !elems.is_empty (); } + + Location get_locus () const { return path.get_locus (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 (HIRVisitor &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<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) + { + 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) + { + 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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<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) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + 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) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleStructItemsRange *clone_tuple_struct_items_impl () const override + { + return new TupleStructItemsRange (*this); + } +}; + +// HIR node representing a tuple struct pattern +class TupleStructPattern : public Pattern +{ + PathInExpression path; + std::unique_ptr<TupleStructItems> items; + + /* TOOD: should this store location data? current accessor uses path location + * data */ + +public: + std::string as_string () const override; + + 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 ()) + {} + + // 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 (); } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 (HIRVisitor &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<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) + { + 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) + { + 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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<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) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + 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) + { + lower_patterns.reserve (other.lower_patterns.size ()); + for (const auto &e : other.lower_patterns) + lower_patterns.push_back (e->clone_pattern ()); + + 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TuplePatternItemsRanged *clone_tuple_pattern_items_impl () const override + { + return new TuplePatternItemsRanged (*this); + } +}; + +// HIR node representing a tuple pattern +class TuplePattern : public Pattern +{ + // bool has_tuple_pattern_items; + std::unique_ptr<TuplePatternItems> items; + + Location locus; + +public: + std::string as_string () const override; + + // Returns true if the tuple pattern has items + bool has_tuple_pattern_items () const { return items != nullptr; } + + 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) + {} + + // 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; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TuplePattern *clone_pattern_impl () const override + { + return new TuplePattern (*this); + } +}; + +// HIR node representing a pattern in parentheses, used to control precedence +class GroupedPattern : public Pattern +{ + std::unique_ptr<Pattern> pattern_in_parens; + Location locus; + +public: + std::string as_string () const override + { + 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) + {} + + // 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; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + GroupedPattern *clone_pattern_impl () const override + { + return new GroupedPattern (*this); + } +}; + +// HIR node representing patterns that can match slices and arrays +class SlicePattern : public Pattern +{ + std::vector<std::unique_ptr<Pattern> > items; + Location locus; + +public: + std::string as_string () const override; + + 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) + { + 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; + + 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; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SlicePattern *clone_pattern_impl () const override + { + return new SlicePattern (*this); + } +}; + +// 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; +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h new file mode 100644 index 0000000..c799b5e --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -0,0 +1,240 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_STATEMENT_H +#define RUST_HIR_STATEMENT_H + +#include "rust-hir.h" +#include "rust-hir-path.h" +#include "rust-hir-expr.h" + +namespace Rust { +namespace HIR { +// Just a semi-colon, which apparently is a statement. +class EmptyStmt : public Stmt +{ + Location locus; + +public: + std::string as_string () const override { return std::string (1, ';'); } + + EmptyStmt (Analysis::NodeMapping mappings, Location locus) + : Stmt (std::move (mappings)), locus (locus) + {} + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + EmptyStmt *clone_stmt_impl () const override { return new EmptyStmt (*this); } +}; + +/* 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; + + std::unique_ptr<Pattern> variables_pattern; + + // bool has_type; + std::unique_ptr<Type> type; + + // bool has_init_expr; + std::unique_ptr<Expr> init_expr; + + Location locus; + +public: + // Returns whether let statement has outer attributes. + bool has_outer_attrs () const { return !outer_attrs.empty (); } + + // Returns whether let statement has a given return type. + bool has_type () const { return type != nullptr; } + + // Returns whether let statement has an initialisation expression. + bool has_init_expr () const { return init_expr != nullptr; } + + std::string as_string () const override; + + LetStmt (Analysis::NodeMapping mappings, + std::unique_ptr<Pattern> variables_pattern, + std::unique_ptr<Expr> init_expr, std::unique_ptr<Type> type, + std::vector<Attribute> outer_attrs, Location locus) + : Stmt (std::move (mappings)), 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) + : Stmt (other.mappings), 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) + {} + + // 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; } + + void accept_vis (HIRVisitor &vis) override; + + HIR::Type *get_type () { return type.get (); } + + HIR::Expr *get_init_expr () { return init_expr.get (); } + + HIR::Pattern *get_pattern () { return variables_pattern.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 (Analysis::NodeMapping mappings, Location locus) + : Stmt (std::move (mappings)), 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 +{ + std::unique_ptr<Expr> expr; + +public: + std::string as_string () const override; + + ExprStmtWithoutBlock (Analysis::NodeMapping mappings, + std::unique_ptr<Expr> expr, Location locus) + : ExprStmt (std::move (mappings), locus), expr (std::move (expr)) + {} + + // Copy constructor with clone + ExprStmtWithoutBlock (ExprStmtWithoutBlock const &other) + : ExprStmt (other), expr (other.expr->clone_expr ()) + {} + + // Overloaded assignment operator to clone + ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock const &other) + { + ExprStmt::operator= (other); + expr = other.expr->clone_expr (); + + return *this; + } + + // move constructors + ExprStmtWithoutBlock (ExprStmtWithoutBlock &&other) = default; + ExprStmtWithoutBlock &operator= (ExprStmtWithoutBlock &&other) = default; + + void accept_vis (HIRVisitor &vis) override; + + Expr *get_expr () { return expr.get (); } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ExprStmtWithoutBlock *clone_stmt_impl () const override + { + return new ExprStmtWithoutBlock (*this); + } +}; + +// Statement containing an expression with a block +class ExprStmtWithBlock : public ExprStmt +{ +public: + std::unique_ptr<ExprWithBlock> expr; + + std::string as_string () const override; + + std::vector<LetStmt *> locals; + + ExprStmtWithBlock (Analysis::NodeMapping mappings, + std::unique_ptr<ExprWithBlock> expr, Location locus) + : ExprStmt (std::move (mappings), locus), expr (std::move (expr)) + {} + + // Copy constructor with clone + ExprStmtWithBlock (ExprStmtWithBlock const &other) + : ExprStmt (other), expr (other.expr->clone_expr_with_block ()) + {} + + // 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; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ExprStmtWithBlock *clone_stmt_impl () const override + { + return new ExprStmtWithBlock (*this); + } +}; + +/* Replaced definition of MacroInvocationSemi with forward decl - defined in + * rust-macro.h */ +class MacroInvocationSemi; +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h new file mode 100644 index 0000000..f8c851c --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -0,0 +1,895 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_H +#define RUST_HIR_TYPE_H + +#include "rust-hir.h" +#include "rust-hir-path.h" + +namespace Rust { +namespace HIR { +// 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 + 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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TraitBound *clone_type_param_bound_impl () const override + { + 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; + // inlined form + std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds; + + Location locus; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ImplTraitType *clone_type_impl () const override + { + return new ImplTraitType (*this); + } + +public: + ImplTraitType ( + Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, + Location locus) + : Type (mappings), type_param_bounds (std::move (type_param_bounds)), + locus (locus) + {} + + // copy constructor with vector clone + ImplTraitType (ImplTraitType const &other) + : Type (other.mappings), locus (other.locus) + { + 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; + mappings = other.mappings; + + 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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &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 */ + TraitObjectType *clone_type_impl () const override + { + return new TraitObjectType (*this); + } + +public: + TraitObjectType ( + Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<TypeParamBound> > type_param_bounds, + Location locus, bool is_dyn_dispatch = false) + : Type (mappings), has_dyn (is_dyn_dispatch), + type_param_bounds (std::move (type_param_bounds)), locus (locus) + {} + + // copy constructor with vector clone + TraitObjectType (TraitObjectType const &other) + : Type (other.mappings), has_dyn (other.has_dyn), locus (other.locus) + { + 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) + { + mappings = other.mappings; + has_dyn = other.has_dyn; + locus = other.locus; + 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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; +}; + +// A type with parentheses around it, used to avoid ambiguity. +class ParenthesisedType : public TypeNoBounds +{ + std::unique_ptr<Type> type_in_parens; + Location locus; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ParenthesisedType *clone_type_impl () const override + { + return new ParenthesisedType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ParenthesisedType *clone_type_no_bounds_impl () const override + { + return new ParenthesisedType (*this); + } + +public: + // Constructor uses Type pointer for polymorphism + ParenthesisedType (Analysis::NodeMapping mappings, + std::unique_ptr<Type> type_inside_parens, Location locus) + : TypeNoBounds (mappings), 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) + : TypeNoBounds (other.mappings), + type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus) + {} + + // overload assignment operator to use custom clone method + ParenthesisedType &operator= (ParenthesisedType const &other) + { + mappings = other.mappings; + 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 override + { + return "(" + type_in_parens->as_string () + ")"; + } + + // Creates a trait bound (clone of this one's trait bound) - HACK + 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; } + + void accept_vis (HIRVisitor &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 */ + ImplTraitTypeOneBound *clone_type_impl () const override + { + return new ImplTraitTypeOneBound (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + ImplTraitTypeOneBound *clone_type_no_bounds_impl () const override + { + return new ImplTraitTypeOneBound (*this); + } + +public: + ImplTraitTypeOneBound (Analysis::NodeMapping mappings, TraitBound trait_bound, + Location locus) + : TypeNoBounds (mappings), trait_bound (std::move (trait_bound)), + locus (locus) + {} + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &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 */ + TraitObjectTypeOneBound *clone_type_impl () const override + { + return new TraitObjectTypeOneBound (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + TraitObjectTypeOneBound *clone_type_no_bounds_impl () const override + { + return new TraitObjectTypeOneBound (*this); + } + +public: + TraitObjectTypeOneBound (Analysis::NodeMapping mappings, + TraitBound trait_bound, Location locus, + bool is_dyn_dispatch = false) + : TypeNoBounds (mappings), has_dyn (is_dyn_dispatch), + trait_bound (std::move (trait_bound)), locus (locus) + {} + + std::string as_string () const override; + + // Creates a trait bound (clone of this one's trait bound) - HACK + 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 HIR::TraitBound (trait_bound); + } + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &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<std::unique_ptr<Type> > elems; + Location locus; + +public: + // Returns whether the tuple type is the unit type, i.e. has no elements. + bool is_unit_type () const { return elems.empty (); } + + TupleType (Analysis::NodeMapping mappings, + std::vector<std::unique_ptr<Type> > elems, Location locus) + : TypeNoBounds (mappings), elems (std::move (elems)), locus (locus) + {} + + // copy constructor with vector clone + TupleType (TupleType const &other) + : TypeNoBounds (other.mappings), locus (other.locus) + { + mappings = other.mappings; + 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; + + 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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + TupleType *clone_type_impl () const override { return new TupleType (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + NeverType *clone_type_impl () const override { return new NeverType (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + NeverType *clone_type_no_bounds_impl () const override + { + return new NeverType (*this); + } + +public: + NeverType (Analysis::NodeMapping mappings, Location locus) + : TypeNoBounds (mappings), locus (locus) + {} + + std::string as_string () const override { return "! (never type)"; } + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &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; + std::unique_ptr<TypeNoBounds> type; + Location locus; + +public: + // Returns whether the pointer is mutable or constant. + PointerType get_pointer_type () const { return pointer_type; } + + // Constructor requires pointer for polymorphism reasons + RawPointerType (Analysis::NodeMapping mappings, PointerType pointer_type, + std::unique_ptr<TypeNoBounds> type_no_bounds, Location locus) + : TypeNoBounds (mappings), pointer_type (pointer_type), + type (std::move (type_no_bounds)), locus (locus) + {} + + // Copy constructor calls custom polymorphic clone function + RawPointerType (RawPointerType const &other) + : TypeNoBounds (other.mappings), pointer_type (other.pointer_type), + type (other.type->clone_type_no_bounds ()), locus (other.locus) + {} + + // overload assignment operator to use custom clone method + RawPointerType &operator= (RawPointerType const &other) + { + mappings = other.mappings; + 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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + RawPointerType *clone_type_impl () const override + { + return new RawPointerType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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; + std::unique_ptr<TypeNoBounds> type; + Location locus; + +public: + // Returns whether the reference is mutable or immutable. + bool is_mut () const { return has_mut; } + + // Returns whether the reference has a lifetime. + bool has_lifetime () const { return !lifetime.is_error (); } + + // Constructor + ReferenceType (Analysis::NodeMapping mappings, bool is_mut, + std::unique_ptr<TypeNoBounds> type_no_bounds, Location locus, + Lifetime lifetime = Lifetime::error ()) + : TypeNoBounds (mappings), 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) + : TypeNoBounds (other.mappings), lifetime (other.lifetime), + has_mut (other.has_mut), type (other.type->clone_type_no_bounds ()), + locus (other.locus) + {} + + // Operator overload assignment operator to custom clone the unique pointer + ReferenceType &operator= (ReferenceType const &other) + { + mappings = other.mappings; + 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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ReferenceType *clone_type_impl () const override + { + return new ReferenceType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 +{ + std::unique_ptr<Type> elem_type; + std::unique_ptr<Expr> size; + Location locus; + +public: + // Constructor requires pointers for polymorphism + ArrayType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type, + std::unique_ptr<Expr> array_size, Location locus) + : TypeNoBounds (mappings), 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) + : TypeNoBounds (mappings), elem_type (other.elem_type->clone_type ()), + size (other.size->clone_expr ()), locus (other.locus) + {} + + // Overload assignment operator to deep copy pointers + ArrayType &operator= (ArrayType const &other) + { + mappings = other.mappings; + 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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + + Type *get_element_type () { return elem_type.get (); } + + Expr *get_size_expr () { return size.get (); } + + Location &get_locus () { return locus; } + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + ArrayType *clone_type_impl () const override { return new ArrayType (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 +{ + std::unique_ptr<Type> elem_type; + Location locus; + +public: + // Constructor requires pointer for polymorphism + SliceType (Analysis::NodeMapping mappings, std::unique_ptr<Type> type, + Location locus) + : TypeNoBounds (mappings), elem_type (std::move (type)), locus (locus) + {} + + // Copy constructor requires deep copy of Type smart pointer + SliceType (SliceType const &other) + : TypeNoBounds (other.mappings), elem_type (other.elem_type->clone_type ()), + locus (other.locus) + {} + + // Overload assignment operator to deep copy + SliceType &operator= (SliceType const &other) + { + mappings = other.mappings; + 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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + SliceType *clone_type_impl () const override { return new SliceType (*this); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + 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 */ + InferredType *clone_type_impl () const override + { + return new InferredType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + InferredType *clone_type_no_bounds_impl () const override + { + return new InferredType (*this); + } + +public: + InferredType (Analysis::NodeMapping mappings, Location locus) + : TypeNoBounds (mappings), locus (locus) + {} + + std::string as_string () const override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &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: + 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. + bool is_error () const { return param_type == nullptr; } + + // Creates an error state param. + static MaybeNamedParam create_error () + { + return MaybeNamedParam ("", UNNAMED, nullptr, 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. + bool has_return_type () const { return return_type != nullptr; } + + // Whether the function has ForLifetimes. + bool has_for_lifetimes () const { return !for_lifetimes.empty (); } + + BareFunctionType (Analysis::NodeMapping mappings, + std::vector<LifetimeParam> lifetime_params, + FunctionQualifiers qualifiers, + std::vector<MaybeNamedParam> named_params, bool is_variadic, + std::unique_ptr<TypeNoBounds> type, Location locus) + : TypeNoBounds (mappings), 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) + : TypeNoBounds (other.mappings), 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) + {} + + // Overload assignment operator to deep copy + BareFunctionType &operator= (BareFunctionType const &other) + { + mappings = other.mappings; + 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 override; + + Location get_locus () const { return locus; } + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + BareFunctionType *clone_type_impl () const override + { + return new BareFunctionType (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + BareFunctionType *clone_type_no_bounds_impl () const override + { + return new BareFunctionType (*this); + } +}; + +// Forward decl - defined in rust-macro.h +class MacroInvocation; + +/* 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 HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir-visitor.h b/gcc/rust/hir/tree/rust-hir-visitor.h new file mode 100644 index 0000000..abb84f5 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-visitor.h @@ -0,0 +1,244 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_VISITOR_H +#define RUST_HIR_VISITOR_H +// Visitor base for HIR + +// full include not required - only forward decls +#include "rust-hir-full-decls.h" + +namespace Rust { +namespace HIR { +/* Pure abstract class that provides an interface for accessing different + * classes of the HIR. */ +class HIRVisitor +{ +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 ¯o) = 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-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-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-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-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-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; + + // TODO: rust-cond-compilation.h visiting? not currently used +}; +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h new file mode 100644 index 0000000..cbaa2e9 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir.h @@ -0,0 +1,1467 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_BASE_H +#define RUST_HIR_BASE_H + +#include "rust-system.h" +#include "rust-token.h" +#include "rust-location.h" +#include "rust-hir-map.h" + +namespace Rust { +typedef std::string Identifier; +typedef int TupleIndex; + +namespace HIR { +// foward decl: ast visitor +class HIRVisitor; + +// Delimiter types - used in macros and whatever. +enum DelimType +{ + PARENS, + SQUARE, + CURLY +}; + +// 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 (HIRVisitor &vis) = 0; + + // Parse attribute input to meta item, if possible + virtual AttrInput *parse_to_meta_item () const { return nullptr; } + +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 (HIRVisitor &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 (HIRVisitor &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 nullptr - 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 ()); + } + } + + bool is_string_lit () const + { + switch (token_id) + { + case STRING_LITERAL: + case BYTE_STRING_LITERAL: + return true; + default: + return false; + } + } + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + + // Return copy of itself but in token stream form. + 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 */ + Token *clone_token_tree_impl () const override { return clone_token_impl (); } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + Token *clone_macro_match_impl () const override + { + return clone_token_impl (); + } +}; + +// 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; } + + 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; + +protected: + DelimTokenTree *clone_delim_tok_tree_impl () const + { + return new DelimTokenTree (*this); + } + + /* Use covariance to implement clone function as returning a DelimTokenTree + * object */ + DelimTokenTree *clone_attr_input_impl () const override + { + return clone_delim_tok_tree_impl (); + } + + /* Use covariance to implement clone function as returning a DelimTokenTree + * object */ + DelimTokenTree *clone_token_tree_impl () const override + { + return clone_delim_tok_tree_impl (); + } + +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) + { + 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; + + 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 override; + + void accept_vis (HIRVisitor &vis) override; + + AttrInput *parse_to_meta_item () const override; + + std::vector<std::unique_ptr<Token> > to_token_stream () const override; + + std::unique_ptr<DelimTokenTree> clone_delim_token_tree () const + { + return std::unique_ptr<DelimTokenTree> (clone_delim_tok_tree_impl ()); + } +}; + +/* 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). */ + 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 override; + + 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. + 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<HIR::SimplePathSegment> single_segments + = {HIR::SimplePathSegment (std::move (str))}; + return SimplePath (std::move (single_segments)); + } +}; + +// aka Attr +// Attribute HIR representation +struct Attribute +{ +private: + SimplePath path; + + // bool has_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 + bool has_attr_input () const { return attr_input != nullptr; } + + // 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) + {} + + // default destructor + ~Attribute () = default; + + // 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 != nullptr) + attr_input = other.attr_input->clone_attr_input (); + } + + // 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 != nullptr) + 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 ()); + } + + // Creates an empty attribute (which is invalid) + static Attribute create_empty () + { + return Attribute (SimplePath::create_empty (), nullptr); + } + + // Returns whether the attribute is considered an "empty" attribute. + bool is_empty () const { return attr_input == nullptr && 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 (); + +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 (HIRVisitor &vis) = 0; + + /* HACK: used to simplify parsing - creates a copy of that type, or returns + * null */ + virtual std::unique_ptr<MetaNameValueStr> to_meta_name_value_str () const + { + return nullptr; + } + + // HACK: used to simplify parsing - same thing + virtual SimplePath to_path_item () const + { + return SimplePath::create_empty (); + } + + virtual Attribute to_attribute () const { return Attribute::create_empty (); } +}; + +// 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)) + {} + + // no destructor definition required + + // default move constructors + AttrInputMetaItemContainer (AttrInputMetaItemContainer &&other) = default; + AttrInputMetaItemContainer &operator= (AttrInputMetaItemContainer &&other) + = default; + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + + // Clones this object. + std::unique_ptr<AttrInputMetaItemContainer> + clone_attr_input_meta_item_container () const + { + return std::unique_ptr<AttrInputMetaItemContainer> ( + clone_attr_input_meta_item_container_impl ()); + } + +protected: + // Use covariance to implement clone function as returning this type + AttrInputMetaItemContainer *clone_attr_input_impl () const override + { + return clone_attr_input_meta_item_container_impl (); + } + + AttrInputMetaItemContainer *clone_attr_input_meta_item_container_impl () const + { + return new AttrInputMetaItemContainer (*this); + } + + // copy constructor with vector clone + AttrInputMetaItemContainer (const AttrInputMetaItemContainer &other) + { + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_meta_item_inner ()); + } + + // copy assignment operator with vector clone + AttrInputMetaItemContainer & + operator= (const AttrInputMetaItemContainer &other) + { + AttrInput::operator= (other); + + items.reserve (other.items.size ()); + for (const auto &e : other.items) + items.push_back (e->clone_meta_item_inner ()); + + return *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 (HIRVisitor &vis) = 0; + + /* HACK: slow way of getting location from base expression through virtual + * methods. */ + virtual Location get_locus_slow () const { return Location (); } + + const Analysis::NodeMapping &get_mappings () const { return mappings; } + +protected: + Stmt (Analysis::NodeMapping mappings) : mappings (std::move (mappings)) {} + + // Clone function implementation as pure virtual method + virtual Stmt *clone_stmt_impl () const = 0; + + Analysis::NodeMapping mappings; +}; + +// Rust "item" HIR 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 + {} + + virtual void accept_vis (HIRVisitor &vis ATTRIBUTE_UNUSED) {} + +protected: + // Constructor + Item (Analysis::NodeMapping mappings, + std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) + : Stmt (std::move (mappings)), 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. */ + Item *clone_stmt_impl () const override { return clone_item_impl (); } +}; + +// forward decl of ExprWithoutBlock +class ExprWithoutBlock; + +// Base expression HIR node - abstract +class Expr +{ + // TODO: move outer attribute data to derived classes? + std::vector<Attribute> outer_attrs; + + Analysis::NodeMapping mappings; + +public: + 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 { return nullptr; } + + // 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 (); } + + // HACK: strictly not needed, but faster than full downcast clone + virtual bool is_expr_without_block () const = 0; + + virtual void accept_vis (HIRVisitor &vis) = 0; + + const Analysis::NodeMapping &get_mappings () const { return mappings; } + +protected: + // Constructor + Expr (Analysis::NodeMapping mappings, + std::vector<Attribute> outer_attribs = std::vector<Attribute> ()) + : outer_attrs (std::move (outer_attribs)), mappings (std::move (mappings)) + {} + + // 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); + } +}; + +// HIR node for an expression without an accompanying block - abstract +class ExprWithoutBlock : public Expr +{ +protected: + // Constructor + ExprWithoutBlock (Analysis::NodeMapping mappings, + std::vector<Attribute> outer_attribs + = std::vector<Attribute> ()) + : Expr (std::move (mappings), 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. */ + ExprWithoutBlock *clone_expr_impl () const override + { + return clone_expr_without_block_impl (); + } + + bool is_expr_without_block () const final override { return true; }; + +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 */ + ExprWithoutBlock *as_expr_without_block () const override + { + 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; + +public: + Location locus; + + IdentifierExpr (Analysis::NodeMapping mappings, Identifier ident, + Location locus = Location (), + std::vector<Attribute> outer_attrs + = std::vector<Attribute> ()) + : ExprWithoutBlock (std::move (mappings), 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 (); } + + void accept_vis (HIRVisitor &vis) override; + + // Clones this object. + std::unique_ptr<IdentifierExpr> clone_identifier_expr () const + { + return std::unique_ptr<IdentifierExpr> (clone_identifier_expr_impl ()); + } + +protected: + // Clone method implementation + IdentifierExpr *clone_expr_without_block_impl () const override + { + return clone_identifier_expr_impl (); + } + + IdentifierExpr *clone_identifier_expr_impl () const + { + return new IdentifierExpr (*this); + } + + IdentifierExpr (IdentifierExpr const &other) = default; + IdentifierExpr &operator= (IdentifierExpr const &other) = default; +}; + +// Pattern base HIR 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 (HIRVisitor &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 HIR - 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 nullptr; + } + /* as pointer, shouldn't require definition beforehand, only forward + * declaration. */ + + virtual void accept_vis (HIRVisitor &vis) = 0; + + virtual Analysis::NodeMapping get_mappings () { return mappings; } + +protected: + Type (Analysis::NodeMapping mappings) : mappings (mappings) {} + + // Clone function implementation as pure virtual method + virtual Type *clone_type_impl () const = 0; + + Analysis::NodeMapping mappings; +}; + +// 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: + TypeNoBounds (Analysis::NodeMapping mappings) : Type (mappings) {} + + // 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. */ + 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 (HIRVisitor &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. + bool is_error () const + { + return lifetime_type == NAMED && lifetime_name.empty (); + } + + std::string as_string () const override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + Lifetime *clone_type_param_bound_impl () const override + { + return new Lifetime (*this); + } +}; + +/* Base generic parameter in HIR. 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 (HIRVisitor &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. + bool has_lifetime_bounds () const { return !lifetime_bounds.empty (); } + + // Returns whether the lifetime param has an outer attribute. + bool has_outer_attribute () const { return !outer_attr.is_empty (); } + + // Creates an error state lifetime param. + static LifetimeParam create_error () + { + return LifetimeParam (Lifetime::error ()); + } + + // Returns whether the lifetime param is in an error state. + 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) + {} + + // 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 override; + + void accept_vis (HIRVisitor &vis) override; + +protected: + /* Use covariance to implement clone function as returning this object rather + * than base */ + LifetimeParam *clone_generic_param_impl () const override + { + return new LifetimeParam (*this); + } +}; + +// A macro item HIR node - potentially abstract base class +class MacroItem : public Item +{ + /*public: + std::string as_string() const;*/ +protected: + MacroItem (Analysis::NodeMapping mappings, + std::vector<Attribute> outer_attribs) + : Item (std::move (mappings), 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. + /*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 (HIRVisitor &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 (HIRVisitor &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 (HIRVisitor &vis) = 0; +}; + +/* A macro invocation item (or statement) HIR node (i.e. semi-coloned macro + * invocation) */ +class MacroInvocationSemi : public MacroItem, + public TraitItem, + public InherentImplItem, + public TraitImplItem +{ + SimplePath path; + // all delim types except curly must have invocation end with a semicolon + DelimType delim_type; + std::vector<std::unique_ptr<TokenTree> > token_trees; + Location locus; + +public: + std::string as_string () const override; + + MacroInvocationSemi (Analysis::NodeMapping mappings, SimplePath macro_path, + DelimType delim_type, + std::vector<std::unique_ptr<TokenTree> > token_trees, + std::vector<Attribute> outer_attribs, Location locus) + : MacroItem (std::move (mappings), 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. */ + + // Move constructors + MacroInvocationSemi (MacroInvocationSemi &&other) = default; + MacroInvocationSemi &operator= (MacroInvocationSemi &&other) = default; + + void accept_vis (HIRVisitor &vis) override; + + // Clones this macro invocation semi. + std::unique_ptr<MacroInvocationSemi> clone_macro_invocation_semi () const + { + return std::unique_ptr<MacroInvocationSemi> ( + clone_macro_invocation_semi_impl ()); + } + +protected: + // 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) + { + 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; + + token_trees.reserve (other.token_trees.size ()); + for (const auto &e : other.token_trees) + token_trees.push_back (e->clone_token_tree ()); + + return *this; + } + + MacroInvocationSemi *clone_macro_invocation_semi_impl () const + { + return new MacroInvocationSemi (*this); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MacroInvocationSemi *clone_item_impl () const override + { + return clone_macro_invocation_semi_impl (); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MacroInvocationSemi *clone_inherent_impl_item_impl () const override + { + return clone_macro_invocation_semi_impl (); + } + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MacroInvocationSemi *clone_trait_impl_item_impl () const override + { + return clone_macro_invocation_semi_impl (); + } + + // FIXME: remove if item impl virtual override works properly + // Use covariance to implement clone function as returning this object rather + // than base + /*MacroInvocationSemi* clone_statement_impl() const override { + return clone_macro_invocation_semi_impl (); + }*/ + + /* Use covariance to implement clone function as returning this object rather + * than base */ + MacroInvocationSemi *clone_trait_item_impl () const override + { + return clone_macro_invocation_semi_impl (); + } +}; + +// A crate HIR object - holds all the data for a single compilation unit +struct Crate +{ + bool has_utf8bom; + bool has_shebang; + + std::vector<Attribute> inner_attrs; + // 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; + + Analysis::NodeMapping mappings; + +public: + // Constructor + Crate (std::vector<std::unique_ptr<Item> > items, + std::vector<Attribute> inner_attrs, Analysis::NodeMapping mappings, + 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)), + mappings (mappings) + {} + + // Copy constructor with vector clone + Crate (Crate const &other) + : has_utf8bom (other.has_utf8bom), has_shebang (other.has_shebang), + inner_attrs (other.inner_attrs), mappings (other.mappings) + { + 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; + mappings = other.mappings; + + 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; + + const Analysis::NodeMapping &get_mappings () const { return mappings; } +}; + +// Base path expression HIR node - abstract +class PathExpr : public ExprWithoutBlock +{ +protected: + PathExpr (Analysis::NodeMapping mappings, + std::vector<Attribute> outer_attribs) + : ExprWithoutBlock (std::move (mappings), 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 HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h new file mode 100644 index 0000000..cc60055 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -0,0 +1,258 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_BASE_H +#define RUST_AST_RESOLVE_BASE_H + +#include "rust-ast-visitor.h" +#include "rust-name-resolver.h" + +#include "rust-diagnostics.h" +#include "rust-location.h" + +namespace Rust { +namespace Resolver { + +class ResolverBase : public AST::ASTVisitor +{ +public: + virtual ~ResolverBase () {} + + // visitor impl + // rust-ast.h + // virtual void visit(AttrInput& attr_input); + // virtual void visit(TokenTree& token_tree); + // virtual void visit(MacroMatch& macro_match); + virtual void visit (AST::Token &tok) {} + virtual void visit (AST::DelimTokenTree &delim_tok_tree) {} + virtual void visit (AST::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // void vsit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (AST::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (AST::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (AST::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (AST::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (AST::PathInExpression &path) {} + virtual void visit (AST::TypePathSegment &segment) {} + virtual void visit (AST::TypePathSegmentGeneric &segment) {} + virtual void visit (AST::TypePathSegmentFunction &segment) {} + virtual void visit (AST::TypePath &path) {} + virtual void visit (AST::QualifiedPathInExpression &path) {} + virtual void visit (AST::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (AST::LiteralExpr &expr) {} + virtual void visit (AST::AttrInputLiteral &attr_input) {} + virtual void visit (AST::MetaItemLitExpr &meta_item) {} + virtual void visit (AST::MetaItemPathLit &meta_item) {} + virtual void visit (AST::BorrowExpr &expr) {} + virtual void visit (AST::DereferenceExpr &expr) {} + virtual void visit (AST::ErrorPropagationExpr &expr) {} + virtual void visit (AST::NegationExpr &expr) {} + virtual void visit (AST::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (AST::ComparisonExpr &expr) {} + virtual void visit (AST::LazyBooleanExpr &expr) {} + virtual void visit (AST::TypeCastExpr &expr) {} + virtual void visit (AST::AssignmentExpr &expr) {} + virtual void visit (AST::CompoundAssignmentExpr &expr) {} + virtual void visit (AST::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (AST::ArrayElemsValues &elems) {} + virtual void visit (AST::ArrayElemsCopied &elems) {} + virtual void visit (AST::ArrayExpr &expr) {} + virtual void visit (AST::ArrayIndexExpr &expr) {} + virtual void visit (AST::TupleExpr &expr) {} + virtual void visit (AST::TupleIndexExpr &expr) {} + virtual void visit (AST::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (AST::StructExprFieldIdentifier &field) {} + virtual void visit (AST::StructExprFieldIdentifierValue &field) {} + virtual void visit (AST::StructExprFieldIndexValue &field) {} + virtual void visit (AST::StructExprStructFields &expr) {} + virtual void visit (AST::StructExprStructBase &expr) {} + virtual void visit (AST::StructExprTuple &expr) {} + virtual void visit (AST::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (AST::EnumExprFieldIdentifier &field) {} + virtual void visit (AST::EnumExprFieldIdentifierValue &field) {} + virtual void visit (AST::EnumExprFieldIndexValue &field) {} + virtual void visit (AST::EnumExprStruct &expr) {} + virtual void visit (AST::EnumExprTuple &expr) {} + virtual void visit (AST::EnumExprFieldless &expr) {} + virtual void visit (AST::CallExpr &expr) {} + virtual void visit (AST::MethodCallExpr &expr) {} + virtual void visit (AST::FieldAccessExpr &expr) {} + virtual void visit (AST::ClosureExprInner &expr) {} + virtual void visit (AST::BlockExpr &expr) {} + virtual void visit (AST::ClosureExprInnerTyped &expr) {} + virtual void visit (AST::ContinueExpr &expr) {} + virtual void visit (AST::BreakExpr &expr) {} + virtual void visit (AST::RangeFromToExpr &expr) {} + virtual void visit (AST::RangeFromExpr &expr) {} + virtual void visit (AST::RangeToExpr &expr) {} + virtual void visit (AST::RangeFullExpr &expr) {} + virtual void visit (AST::RangeFromToInclExpr &expr) {} + virtual void visit (AST::RangeToInclExpr &expr) {} + virtual void visit (AST::ReturnExpr &expr) {} + virtual void visit (AST::UnsafeBlockExpr &expr) {} + virtual void visit (AST::LoopExpr &expr) {} + virtual void visit (AST::WhileLoopExpr &expr) {} + virtual void visit (AST::WhileLetLoopExpr &expr) {} + virtual void visit (AST::ForLoopExpr &expr) {} + virtual void visit (AST::IfExpr &expr) {} + virtual void visit (AST::IfExprConseqElse &expr) {} + virtual void visit (AST::IfExprConseqIf &expr) {} + virtual void visit (AST::IfExprConseqIfLet &expr) {} + virtual void visit (AST::IfLetExpr &expr) {} + virtual void visit (AST::IfLetExprConseqElse &expr) {} + virtual void visit (AST::IfLetExprConseqIf &expr) {} + virtual void visit (AST::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (AST::MatchCaseBlockExpr &match_case) {} + // virtual void visit (AST::MatchCaseExpr &match_case) {} + virtual void visit (AST::MatchExpr &expr) {} + virtual void visit (AST::AwaitExpr &expr) {} + virtual void visit (AST::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (AST::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (AST::LifetimeWhereClauseItem &item) {} + virtual void visit (AST::TypeBoundWhereClauseItem &item) {} + virtual void visit (AST::Method &method) {} + virtual void visit (AST::ModuleBodied &module) {} + virtual void visit (AST::ModuleNoBody &module) {} + virtual void visit (AST::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (AST::UseTreeGlob &use_tree) {} + virtual void visit (AST::UseTreeList &use_tree) {} + virtual void visit (AST::UseTreeRebind &use_tree) {} + virtual void visit (AST::UseDeclaration &use_decl) {} + virtual void visit (AST::Function &function) {} + virtual void visit (AST::TypeAlias &type_alias) {} + virtual void visit (AST::StructStruct &struct_item) {} + virtual void visit (AST::TupleStruct &tuple_struct) {} + virtual void visit (AST::EnumItem &item) {} + virtual void visit (AST::EnumItemTuple &item) {} + virtual void visit (AST::EnumItemStruct &item) {} + virtual void visit (AST::EnumItemDiscriminant &item) {} + virtual void visit (AST::Enum &enum_item) {} + virtual void visit (AST::Union &union_item) {} + virtual void visit (AST::ConstantItem &const_item) {} + virtual void visit (AST::StaticItem &static_item) {} + virtual void visit (AST::TraitItemFunc &item) {} + virtual void visit (AST::TraitItemMethod &item) {} + virtual void visit (AST::TraitItemConst &item) {} + virtual void visit (AST::TraitItemType &item) {} + virtual void visit (AST::Trait &trait) {} + virtual void visit (AST::InherentImpl &impl) {} + virtual void visit (AST::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (AST::ExternalStaticItem &item) {} + virtual void visit (AST::ExternalFunctionItem &item) {} + virtual void visit (AST::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (AST::MacroMatchFragment &match) {} + virtual void visit (AST::MacroMatchRepetition &match) {} + virtual void visit (AST::MacroMatcher &matcher) {} + virtual void visit (AST::MacroRulesDefinition &rules_def) {} + virtual void visit (AST::MacroInvocation ¯o_invoc) {} + virtual void visit (AST::MetaItemPath &meta_item) {} + virtual void visit (AST::MetaItemSeq &meta_item) {} + virtual void visit (AST::MetaWord &meta_item) {} + virtual void visit (AST::MetaNameValueStr &meta_item) {} + virtual void visit (AST::MetaListPaths &meta_item) {} + virtual void visit (AST::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (AST::LiteralPattern &pattern) {} + virtual void visit (AST::IdentifierPattern &pattern) {} + virtual void visit (AST::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (AST::RangePatternBoundLiteral &bound) {} + virtual void visit (AST::RangePatternBoundPath &bound) {} + virtual void visit (AST::RangePatternBoundQualPath &bound) {} + virtual void visit (AST::RangePattern &pattern) {} + virtual void visit (AST::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (AST::StructPatternFieldTuplePat &field) {} + virtual void visit (AST::StructPatternFieldIdentPat &field) {} + virtual void visit (AST::StructPatternFieldIdent &field) {} + virtual void visit (AST::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (AST::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (AST::TupleStructItemsRange &tuple_items) {} + virtual void visit (AST::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (AST::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (AST::TuplePattern &pattern) {} + virtual void visit (AST::GroupedPattern &pattern) {} + virtual void visit (AST::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (AST::EmptyStmt &stmt) {} + virtual void visit (AST::LetStmt &stmt) {} + virtual void visit (AST::ExprStmtWithoutBlock &stmt) {} + virtual void visit (AST::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (AST::TraitBound &bound) {} + virtual void visit (AST::ImplTraitType &type) {} + virtual void visit (AST::TraitObjectType &type) {} + virtual void visit (AST::ParenthesisedType &type) {} + virtual void visit (AST::ImplTraitTypeOneBound &type) {} + virtual void visit (AST::TraitObjectTypeOneBound &type) {} + virtual void visit (AST::TupleType &type) {} + virtual void visit (AST::NeverType &type) {} + virtual void visit (AST::RawPointerType &type) {} + virtual void visit (AST::ReferenceType &type) {} + virtual void visit (AST::ArrayType &type) {} + virtual void visit (AST::SliceType &type) {} + virtual void visit (AST::InferredType &type) {} + virtual void visit (AST::BareFunctionType &type) {} + +protected: + ResolverBase (NodeId parent) + : resolver (Resolver::get ()), resolved_node (UNKNOWN_NODEID), + parent (parent), locus (Location ()) + {} + + bool resolved () const { return resolved_node != UNKNOWN_NODEID; } + + Resolver *resolver; + NodeId resolved_node; + NodeId parent; + Location locus; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_BASE_H diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h new file mode 100644 index 0000000..9e98fda --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -0,0 +1,105 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_EXPR_H +#define RUST_AST_RESOLVE_EXPR_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class ResolveExpr : public ResolverBase +{ +public: + static void go (AST::Expr *expr, NodeId parent) + { + ResolveExpr resolver (parent); + expr->accept_vis (resolver); + }; + + ~ResolveExpr () {} + + void visit (AST::PathInExpression &expr) + { + if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + { + rust_error_at (expr.get_locus (), "unknown path %s", + expr.as_string ().c_str ()); + return; + } + else + { + resolver->insert_resolved_name (expr.get_node_id (), resolved_node); + resolver->insert_new_definition (expr.get_node_id (), + Definition{expr.get_node_id (), + parent}); + } + } + + void visit (AST::ReturnExpr &expr) + { + if (expr.has_returned_expr ()) + ResolveExpr::go (expr.get_returned_expr ().get (), expr.get_node_id ()); + } + + void visit (AST::CallExpr &expr) + { + ResolveExpr::go (expr.get_function_expr ().get (), expr.get_node_id ()); + expr.iterate_params ([&] (AST::Expr *p) mutable -> bool { + ResolveExpr::go (p, expr.get_node_id ()); + return true; + }); + // resolver->insert_resolved_name(NodeId refId,NodeId defId) + } + + void visit (AST::AssignmentExpr &expr) + { + ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); + ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); + } + + void visit (AST::IdentifierExpr &expr) + { + if (!resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + { + rust_error_at (expr.get_locus (), "failed to find name: %s", + expr.as_string ().c_str ()); + return; + } + + resolver->insert_resolved_name (expr.get_node_id (), resolved_node); + resolver->insert_new_definition (expr.get_node_id (), + Definition{expr.get_node_id (), parent}); + } + + void visit (AST::ArithmeticOrLogicalExpr &expr) + { + ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); + ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); + } + +private: + ResolveExpr (NodeId parent) : ResolverBase (parent) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_EXPR_H diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h new file mode 100644 index 0000000..2c21a52 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -0,0 +1,79 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_ITEM_H +#define RUST_AST_RESOLVE_ITEM_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" +#include "rust-ast-resolve-type.h" +#include "rust-ast-resolve-pattern.h" +#include "rust-ast-resolve-stmt.h" + +namespace Rust { +namespace Resolver { + +class ResolveItem : public ResolverBase +{ +public: + static void go (AST::Item *item) + { + ResolveItem resolver; + item->accept_vis (resolver); + }; + + ~ResolveItem () {} + + void visit (AST::Function &function) + { + if (function.has_return_type ()) + ResolveType::go (function.get_return_type ().get (), + function.get_node_id ()); + + for (auto ¶m : function.get_function_params ()) + { + ResolveType::go (param.get_type ().get (), param.get_node_id ()); + PatternDeclaration::go (param.get_pattern ().get (), + param.get_node_id ()); + } + + // setup parent scoping for names + NodeId scope_node_id = function.get_definition ()->get_node_id (); + resolver->get_name_scope ().push (scope_node_id); + resolver->get_type_scope ().push (scope_node_id); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + + function.get_definition ()->iterate_stmts ( + [&] (AST::Stmt *s) mutable -> bool { + ResolveStmt::go (s, s->get_node_id ()); + return true; + }); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); + } + +private: + ResolveItem () : ResolverBase (UNKNOWN_NODEID) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_ITEM_H diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h new file mode 100644 index 0000000..fc2da70 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -0,0 +1,97 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_PATTERN_H +#define RUST_AST_RESOLVE_PATTERN_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class ResolvePattern : public ResolverBase +{ +public: + static void go (AST::Pattern *pattern, NodeId parent) + { + ResolvePattern resolver (parent); + + pattern->accept_vis (resolver); + if (resolver.resolved_node == UNKNOWN_NODEID) + { + rust_error_at (resolver.locus, "failed to resolve pattern %s", + pattern->as_string ().c_str ()); + } + }; + + ~ResolvePattern () {} + + void visit (AST::IdentifierPattern &pattern) + { + if (resolver->get_name_scope ().lookup (pattern.get_ident (), + &resolved_node)) + { + resolver->insert_resolved_name (pattern.get_node_id (), resolved_node); + resolver->insert_new_definition (pattern.get_node_id (), + Definition{pattern.get_node_id (), + parent}); + } + } + +private: + ResolvePattern (NodeId parent) : ResolverBase (parent) {} +}; + +class PatternDeclaration : public ResolverBase +{ +public: + static void go (AST::Pattern *pattern, NodeId parent) + { + PatternDeclaration resolver (parent); + + pattern->accept_vis (resolver); + if (resolver.resolved_node != UNKNOWN_NODEID) + { + // print both locations?! + rust_error_at (resolver.locus, "duplicate pattern %s", + pattern->as_string ().c_str ()); + } + }; + + ~PatternDeclaration () {} + + void visit (AST::IdentifierPattern &pattern) + { + // if we have a duplicate id this then allows for shadowing correctly + // as new refs to this decl will match back here so it is ok to overwrite + resolver->get_name_scope ().insert (pattern.get_ident (), + pattern.get_node_id ()); + resolver->insert_new_definition (pattern.get_node_id (), + Definition{pattern.get_node_id (), + parent}); + } + +private: + PatternDeclaration (NodeId parent) : ResolverBase (parent) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_PATTERN_H diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h new file mode 100644 index 0000000..20d40f1 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -0,0 +1,64 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_STMT_H +#define RUST_AST_RESOLVE_STMT_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" +#include "rust-ast-resolve-type.h" +#include "rust-ast-resolve-pattern.h" +#include "rust-ast-resolve-expr.h" + +namespace Rust { +namespace Resolver { + +class ResolveStmt : public ResolverBase +{ +public: + static void go (AST::Stmt *stmt, NodeId parent) + { + ResolveStmt resolver (parent); + stmt->accept_vis (resolver); + }; + + ~ResolveStmt () {} + + void visit (AST::ExprStmtWithoutBlock &stmt) + { + ResolveExpr::go (stmt.get_expr ().get (), stmt.get_node_id ()); + } + + void visit (AST::LetStmt &stmt) + { + PatternDeclaration::go (stmt.get_pattern ().get (), stmt.get_node_id ()); + if (stmt.has_type ()) + ResolveType::go (stmt.get_type ().get (), stmt.get_node_id ()); + + if (stmt.has_init_expr ()) + ResolveExpr::go (stmt.get_init_expr ().get (), stmt.get_node_id ()); + } + +private: + ResolveStmt (NodeId parent) : ResolverBase (parent) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_STMT_H diff --git a/gcc/rust/resolve/rust-ast-resolve-toplevel.h b/gcc/rust/resolve/rust-ast-resolve-toplevel.h new file mode 100644 index 0000000..fcc9663 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-toplevel.h @@ -0,0 +1,54 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_TOPLEVEL_H +#define RUST_AST_RESOLVE_TOPLEVEL_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class ResolveTopLevel : public ResolverBase +{ +public: + static void go (AST::Item *item) + { + ResolveTopLevel resolver; + item->accept_vis (resolver); + }; + + ~ResolveTopLevel () {} + + void visit (AST::Function &function) + { + // function_names are simple std::String identifiers so this can be a + // NodeId mapping to the Function node + resolver->get_name_scope ().insert (function.get_function_name (), + function.get_node_id ()); + } + +private: + ResolveTopLevel () : ResolverBase (UNKNOWN_NODEID) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_TOPLEVEL_H diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h new file mode 100644 index 0000000..3cffa77 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -0,0 +1,66 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_TYPE_H +#define RUST_AST_RESOLVE_TYPE_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class ResolveType : public ResolverBase +{ +public: + static void go (AST::Type *type, NodeId parent) + { + ResolveType resolver (parent); + + type->accept_vis (resolver); + if (resolver.resolved_node == UNKNOWN_NODEID) + { + rust_error_at (resolver.locus, "failed to resolve type %s", + type->as_string ().c_str ()); + } + }; + + ~ResolveType () {} + + virtual void visit (AST::TypePath &path) + { + // this will need changed to handle mod/crate/use globs and look + // at the segments in granularity + locus = path.get_locus (); + if (resolver->get_type_scope ().lookup (path.as_string (), &resolved_node)) + { + resolver->insert_resolved_type (path.get_node_id (), resolved_node); + resolver->insert_new_definition (path.get_node_id (), + Definition{path.get_node_id (), + parent}); + } + } + +private: + ResolveType (NodeId parent) : ResolverBase (parent) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_TYPE_H diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc new file mode 100644 index 0000000..57bd0f3 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -0,0 +1,252 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-ast-resolve.h" +#include "rust-ast-resolve-toplevel.h" +#include "rust-ast-resolve-item.h" +#include "rust-ast-full.h" +#include "rust-tyty.h" + +#define MKBUILTIN_TYPE(_X, _R, _TY) \ + do \ + { \ + AST::PathIdentSegment seg (_X); \ + auto typePath = ::std::unique_ptr<AST::TypePathSegment> ( \ + new AST::TypePathSegment (::std::move (seg), false, \ + Linemap::predeclared_location ())); \ + ::std::vector< ::std::unique_ptr<AST::TypePathSegment> > segs; \ + segs.push_back (::std::move (typePath)); \ + auto builtin_type \ + = new AST::TypePath (::std::move (segs), \ + Linemap::predeclared_location (), false); \ + _R.push_back (builtin_type); \ + tyctx->insert_builtin (_TY->get_ref (), builtin_type->get_node_id (), \ + _TY); \ + } \ + while (0) + +namespace Rust { +namespace Resolver { + +// Resolver + +Resolver::Resolver () + : mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()), + name_scope (Scope (mappings->get_current_crate ())), + type_scope (Scope (mappings->get_current_crate ())) +{ + generate_builtins (); +} + +Resolver * +Resolver::get () +{ + static Resolver *instance; + if (instance == nullptr) + instance = new Resolver (); + + return instance; +} + +void +Resolver::push_new_name_rib (Rib *r) +{ + rust_assert (name_ribs.find (r->get_node_id ()) == name_ribs.end ()); + name_ribs[r->get_node_id ()] = r; +} + +void +Resolver::push_new_type_rib (Rib *r) +{ + if (type_ribs.size () == 0) + global_type_node_id = r->get_node_id (); + + rust_assert (type_ribs.find (r->get_node_id ()) == type_ribs.end ()); + type_ribs[r->get_node_id ()] = r; +} + +bool +Resolver::find_name_rib (NodeId id, Rib **rib) +{ + auto it = name_ribs.find (id); + if (it == name_ribs.end ()) + return false; + + *rib = it->second; + return true; +} + +bool +Resolver::find_type_rib (NodeId id, Rib **rib) +{ + auto it = type_ribs.find (id); + if (it == type_ribs.end ()) + return false; + + *rib = it->second; + return true; +} + +void +Resolver::insert_builtin_types (Rib *r) +{ + auto builtins = get_builtin_types (); + for (auto it = builtins.begin (); it != builtins.end (); it++) + r->insert_name ((*it)->as_string (), (*it)->get_node_id ()); +} + +std::vector<AST::TypePath *> & +Resolver::get_builtin_types () +{ + return builtins; +} + +void +Resolver::generate_builtins () +{ + auto u8 + = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U8); + auto u16 + = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U16); + auto u32 + = new TyTy::UintType (mappings->get_next_hir_id (), TyTy::UintType::U32); + auto i8 = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I8); + auto i16 + = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I16); + auto i32 + = new TyTy::IntType (mappings->get_next_hir_id (), TyTy::IntType::I32); + auto rbool = new TyTy::BoolType (mappings->get_next_hir_id ()); + + MKBUILTIN_TYPE ("u8", builtins, u8); + MKBUILTIN_TYPE ("u16", builtins, u16); + MKBUILTIN_TYPE ("u32", builtins, u32); + MKBUILTIN_TYPE ("i8", builtins, i8); + MKBUILTIN_TYPE ("i16", builtins, i16); + MKBUILTIN_TYPE ("i32", builtins, i32); + MKBUILTIN_TYPE ("bool", builtins, rbool); +} + +void +Resolver::insert_new_definition (NodeId id, Definition def) +{ + auto it = name_definitions.find (id); + rust_assert (it == name_definitions.end ()); + + name_definitions[id] = def; +} + +bool +Resolver::lookup_definition (NodeId id, Definition *def) +{ + auto it = name_definitions.find (id); + if (it == name_definitions.end ()) + return false; + + *def = it->second; + return true; +} + +void +Resolver::insert_resolved_name (NodeId refId, NodeId defId) +{ + auto it = resolved_names.find (refId); + rust_assert (it == resolved_names.end ()); + + resolved_names[refId] = defId; +} + +bool +Resolver::lookup_resolved_name (NodeId refId, NodeId *defId) +{ + auto it = resolved_names.find (refId); + if (it == resolved_names.end ()) + return false; + + *defId = it->second; + return true; +} + +void +Resolver::insert_resolved_type (NodeId refId, NodeId defId) +{ + auto it = resolved_types.find (refId); + rust_assert (it == resolved_types.end ()); + + resolved_types[refId] = defId; +} + +bool +Resolver::lookup_resolved_type (NodeId refId, NodeId *defId) +{ + auto it = resolved_types.find (refId); + if (it == resolved_types.end ()) + return false; + + *defId = it->second; + return true; +} + +// NameResolution + +NameResolution * +NameResolution::get () +{ + static NameResolution *instance; + if (instance == nullptr) + instance = new NameResolution (); + + return instance; +} + +NameResolution::NameResolution () + : resolver (Resolver::get ()), mappings (Analysis::Mappings::get ()) +{ + // these are global + resolver->get_type_scope ().push (mappings->get_next_node_id ()); + resolver->insert_builtin_types (resolver->get_type_scope ().peek ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); +} + +void +NameResolution::Resolve (AST::Crate &crate) +{ + auto resolver = get (); + resolver->go (crate); +} + +void +NameResolution::go (AST::Crate &crate) +{ + // setup parent scoping for names + resolver->get_name_scope ().push (crate.get_node_id ()); + resolver->push_new_name_rib (resolver->get_name_scope ().peek ()); + // setup parent scoping for new types + resolver->get_type_scope ().push (mappings->get_next_node_id ()); + resolver->push_new_type_rib (resolver->get_type_scope ().peek ()); + + // first gather the top-level namespace names then we drill down + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + ResolveTopLevel::go (it->get ()); + + // next we can drill down into the items and their scopes + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + ResolveItem::go (it->get ()); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/resolve/rust-ast-resolve.h b/gcc/rust/resolve/rust-ast-resolve.h new file mode 100644 index 0000000..29ae0ab --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve.h @@ -0,0 +1,50 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_H +#define RUST_AST_RESOLVE_H + +#include "rust-name-resolver.h" +#include "rust-ast-full.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace Resolver { + +class NameResolution +{ +public: + static void Resolve (AST::Crate &crate); + + static NameResolution *get (); + + ~NameResolution () {} + +private: + void go (AST::Crate &crate); + + NameResolution (); + + Resolver *resolver; + Analysis::Mappings *mappings; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_H diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h new file mode 100644 index 0000000..2aa592c --- /dev/null +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -0,0 +1,222 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_NAME_RESOLVER_H +#define RUST_NAME_RESOLVER_H + +#include "rust-system.h" +#include "rust-hir-map.h" +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver { + +class Rib +{ +public: + // Rusts uses local_def_ids assigned by def_collector on the AST + // lets use NodeId instead + Rib (CrateNum crateNum, NodeId node_id) + : crate_num (crateNum), node_id (node_id) + {} + + ~Rib () {} + + void insert_name (std::string ident, NodeId id) + { + mappings[ident] = id; + decls_within_rib.insert (id); + } + + bool lookup_name (std::string ident, NodeId *id) + { + auto it = mappings.find (ident); + if (it == mappings.end ()) + return false; + + *id = it->second; + return true; + } + + CrateNum get_crate_num () const { return crate_num; } + NodeId get_node_id () const { return node_id; } + + void iterate_decls (std::function<bool (NodeId)> cb) + { + for (auto it : decls_within_rib) + { + if (!cb (it)) + return; + } + } + +private: + CrateNum crate_num; + NodeId node_id; + std::map<std::string, NodeId> mappings; + std::set<NodeId> decls_within_rib; +}; + +class Scope +{ +public: + Scope (CrateNum crate_num) : crate_num (crate_num) {} + ~Scope () {} + + void insert (std::string ident, NodeId id) + { + peek ()->insert_name (ident, id); + } + + bool lookup (std::string ident, NodeId *id) + { + NodeId lookup = UNKNOWN_NODEID; + iterate ([&] (Rib *r) mutable -> bool { + if (r->lookup_name (ident, &lookup)) + return false; + return true; + }); + + *id = lookup; + return lookup != UNKNOWN_NODEID; + } + + void iterate (std::function<bool (Rib *)> cb) + { + for (auto it = stack.rbegin (); it != stack.rend (); ++it) + { + if (!cb (*it)) + return; + } + } + + Rib *peek () { return stack.back (); } + + void push (NodeId id) { stack.push_back (new Rib (get_crate_num (), id)); } + + Rib *pop () + { + Rib *r = peek (); + stack.pop_back (); + return r; + } + + CrateNum get_crate_num () const { return crate_num; } + +private: + CrateNum crate_num; + std::vector<Rib *> stack; +}; + +// This can map simple NodeIds for names to their parent node +// for example: +// +// var x = y + 1; +// +// say y has node id=1 and the plus_expression has id=2 +// then the Definition will have +// Definition { node=1, parent=2 } +// this will be used later to gather the ribs for the type inferences context +// +// if parent is UNKNOWN_NODEID then this is a root declaration +// say the var_decl hasa node_id=4; +// the parent could be a BLOCK_Expr node_id but lets make it UNKNOWN_NODE_ID so +// we know when it terminates +struct Definition +{ + NodeId node; + NodeId parent; + // add kind ? +}; + +class Resolver +{ +public: + static Resolver *get (); + ~Resolver () {} + + // these builtin types + void insert_builtin_types (Rib *r); + + // these will be required for type resolution passes to + // map back to tyty nodes + std::vector<AST::TypePath *> &get_builtin_types (); + + void push_new_name_rib (Rib *r); + void push_new_type_rib (Rib *r); + + bool find_name_rib (NodeId id, Rib **rib); + bool find_type_rib (NodeId id, Rib **rib); + + void insert_new_definition (NodeId id, Definition def); + bool lookup_definition (NodeId id, Definition *def); + + void insert_resolved_name (NodeId refId, NodeId defId); + bool lookup_resolved_name (NodeId refId, NodeId *defId); + + void insert_resolved_type (NodeId refId, NodeId defId); + bool lookup_resolved_type (NodeId refId, NodeId *defId); + + // proxy for scoping + Scope &get_name_scope () { return name_scope; } + Scope &get_type_scope () { return type_scope; } + + NodeId get_global_type_node_id () { return global_type_node_id; } + +private: + Resolver (); + + void generate_builtins (); + + Analysis::Mappings *mappings; + TypeCheckContext *tyctx; + + std::vector<AST::TypePath *> builtins; + + Scope name_scope; + Scope type_scope; + + NodeId global_type_node_id; + + // map a AST Node to a Rib + std::map<NodeId, Rib *> name_ribs; + std::map<NodeId, Rib *> type_ribs; + + // map any Node to its Definition + // ie any name or type usage + std::map<NodeId, Definition> name_definitions; + + // Rust uses DefIds to namespace these under a crate_num + // but then it uses the def_collector to assign local_defids + // to each ast node as well. not sure if this is going to fit + // with gcc very well to compile a full crate in one go but we will + // see. + + // these are of the form ref->Def-NodeId + // we need two namespaces one for names and ones for types + std::map<NodeId, NodeId> resolved_names; + std::map<NodeId, NodeId> resolved_types; + + std::map<NodeId, std::set<NodeId> > nameDefNodeIdToRibs; + std::map<NodeId, std::set<NodeId> > typeDefNodeIdToRibs; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_NAME_RESOLVER_H diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index da50948..17ff24a 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -1,5 +1,23 @@ -#include "rust-session-manager.h" +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. +// #include "rust-session-manager.h" +#include "rust-session-manager.h" #include "rust-diagnostics.h" #include "diagnostic.h" #include "input.h" @@ -8,17 +26,15 @@ #include "tm.h" #include "tm_p.h" +#include "rust-target.h" + #include "rust-lex.h" #include "rust-parse.h" -#include "rust-scan.h" -#include "rust-name-resolution.h" -#include "rust-type-resolution.h" -#include "rust-compile.h" #include "rust-macro-expand.h" - -#include "rust-target.h" - -#include <algorithm> +#include "rust-ast-resolve.h" +#include "rust-ast-lower.h" +#include "rust-hir-type-check.h" +#include "rust-compile.h" extern Linemap * rust_get_linemap (); @@ -381,6 +397,10 @@ Session::enable_dump (std::string arg) // return false; options.dump_option = CompileOptions::TARGET_OPTION_DUMP; } + else if (arg == "hir") + { + options.dump_option = CompileOptions::HIR_DUMP; + } else if (arg == "") { rust_error_at (Location (), "dump option was not given a name. choose " @@ -405,6 +425,7 @@ Session::parse_files (int num_files, const char **files) { for (int i = 0; i < num_files; i++) { + printf ("Attempting to parse file: %s\n", files[i]); parse_file (files[i]); } /* TODO: should semantic analysis be dealed with here? or per file? for now, @@ -431,6 +452,10 @@ Session::parse_file (const char *filename) // generate crate from parser auto parsed_crate = parser.parse_crate (); + // setup the mappings for this AST + auto mappings = Analysis::Mappings::get (); + mappings->insert_ast_crate (&parsed_crate); + // give a chance to give some debug switch (options.dump_option) { @@ -507,8 +532,32 @@ Session::parse_file (const char *filename) if (saw_errors ()) return; + // lower AST to HIR + HIR::Crate hir = lower_ast (parsed_crate); + if (options.dump_option == CompileOptions::HIR_DUMP) + { + fprintf (stderr, "%s", hir.as_string ().c_str ()); + return; + } + + if (saw_errors ()) + return; + + // type resolve + type_resolution (hir); + + if (saw_errors ()) + return; + // do compile - Compile::Compilation::Compile (parsed_crate, backend); + Compile::Context ctx (backend); + Compile::CompileCrate::Compile (hir, &ctx); + + if (saw_errors ()) + return; + + // pass to GCC + ctx.write_to_backend (); } // TODO: actually implement method @@ -736,13 +785,27 @@ void Session::resolution (AST::Crate &crate) { fprintf (stderr, "started name resolution\n"); - Analysis::TopLevelScan toplevel (crate); - // Name resolution must be in front of type resolution - Analysis::NameResolution::Resolve (crate, toplevel); - Analysis::TypeResolution::Resolve (crate, toplevel); + Resolver::NameResolution::Resolve (crate); fprintf (stderr, "finished name resolution\n"); } +HIR::Crate +Session::lower_ast (AST::Crate &crate) +{ + fprintf (stderr, "started lowering AST\n"); + auto hir = HIR::ASTLowering::Resolve (crate); + fprintf (stderr, "finished lowering AST\n"); + return hir; +} + +void +Session::type_resolution (HIR::Crate &crate) +{ + fprintf (stderr, "started type resolution\n"); + Resolver::TypeResolution::Resolve (crate); + fprintf (stderr, "finished type resolution\n"); +} + void TargetOptions::dump_target_options () const { diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index bdeeeec..4836cc8 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -1,6 +1,24 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. +// #include "rust-session-manager.h" + #ifndef RUST_SESSION_MANAGER_H #define RUST_SESSION_MANAGER_H -// Session manager - controls compiler session. #include "config.h" #include "system.h" @@ -11,12 +29,6 @@ #include "rust-linemap.h" #include "rust-backend.h" -#include <string> -#include <unordered_map> -#include <unordered_set> -#include <vector> -#include <utility> - namespace Rust { // parser forward decl template <typename ManagedTokenSource> class Parser; @@ -25,6 +37,10 @@ class Lexer; namespace AST { struct Crate; } +// crate forward decl +namespace HIR { +struct Crate; +} /* Data related to target, most useful for conditional compilation and * whatever. */ @@ -32,7 +48,7 @@ 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; + std::unordered_map<std::string, std::unordered_set<std::string> > features; public: // Returns whether a key is defined in the feature set. @@ -160,6 +176,7 @@ struct CompileOptions EXPANSION_DUMP, RESOLUTION_DUMP, TARGET_OPTION_DUMP, + HIR_DUMP, // TODO: add more? } dump_option; @@ -227,6 +244,11 @@ private: * Performs name resolution and type resolution, maybe complete gated * feature checking, maybe create buffered lints in future. */ void resolution (AST::Crate &crate); + /* This lowers the AST down to HIR and assigns all mappings from AST + * NodeIds back to HirIds */ + HIR::Crate lower_ast (AST::Crate &crate); + /* This adds the type resolution process */ + void type_resolution (HIR::Crate &crate); }; } // namespace Rust diff --git a/gcc/rust/rust-system.h b/gcc/rust/rust-system.h index a711fdc..26c9b33 100644 --- a/gcc/rust/rust-system.h +++ b/gcc/rust/rust-system.h @@ -40,6 +40,7 @@ #include <string> #include <deque> #include <functional> +#include <memory> // Rust frontend requires C++11 minimum, so will have unordered_map and set #include <unordered_map> @@ -56,7 +57,7 @@ #include "coretypes.h" #include "diagnostic-core.h" /* For error_at and friends. */ -#include "intl.h" /* For _(). */ +#include "intl.h" /* For _(). */ // When using gcc, rust_assert is just gcc_assert. #define rust_assert(EXPR) gcc_assert (EXPR) diff --git a/gcc/rust/typecheck/rust-hir-type-check-base.h b/gcc/rust/typecheck/rust-hir-type-check-base.h new file mode 100644 index 0000000..78afff9 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-base.h @@ -0,0 +1,256 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_BASE +#define RUST_HIR_TYPE_CHECK_BASE + +#include "rust-diagnostics.h" +#include "rust-hir-type-check.h" +#include "rust-name-resolver.h" +#include "rust-hir-visitor.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace Resolver { + +// base class to allow derivatives to overload as needed +class TypeCheckBase : public HIR::HIRVisitor +{ +public: + virtual ~TypeCheckBase () {} + + // visitor impl + // rust-ast.h + // virtual void visit(AttrInput& attr_input); + // virtual void visit(TokenTree& token_tree); + // virtual void visit(MacroMatch& macro_match); + virtual void visit (HIR::Token &tok) {} + virtual void visit (HIR::DelimTokenTree &delim_tok_tree) {} + virtual void visit (HIR::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // void vsit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (HIR::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (HIR::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (HIR::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (HIR::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (HIR::PathInExpression &path) {} + virtual void visit (HIR::TypePathSegment &segment) {} + virtual void visit (HIR::TypePathSegmentGeneric &segment) {} + virtual void visit (HIR::TypePathSegmentFunction &segment) {} + virtual void visit (HIR::TypePath &path) {} + virtual void visit (HIR::QualifiedPathInExpression &path) {} + virtual void visit (HIR::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (HIR::LiteralExpr &expr) {} + virtual void visit (HIR::AttrInputLiteral &attr_input) {} + virtual void visit (HIR::MetaItemLitExpr &meta_item) {} + virtual void visit (HIR::MetaItemPathLit &meta_item) {} + virtual void visit (HIR::BorrowExpr &expr) {} + virtual void visit (HIR::DereferenceExpr &expr) {} + virtual void visit (HIR::ErrorPropagationExpr &expr) {} + virtual void visit (HIR::NegationExpr &expr) {} + virtual void visit (HIR::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (HIR::ComparisonExpr &expr) {} + virtual void visit (HIR::LazyBooleanExpr &expr) {} + virtual void visit (HIR::TypeCastExpr &expr) {} + virtual void visit (HIR::AssignmentExpr &expr) {} + virtual void visit (HIR::CompoundAssignmentExpr &expr) {} + virtual void visit (HIR::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (HIR::ArrayElemsValues &elems) {} + virtual void visit (HIR::ArrayElemsCopied &elems) {} + virtual void visit (HIR::ArrayExpr &expr) {} + virtual void visit (HIR::ArrayIndexExpr &expr) {} + virtual void visit (HIR::TupleExpr &expr) {} + virtual void visit (HIR::TupleIndexExpr &expr) {} + virtual void visit (HIR::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (HIR::StructExprFieldIdentifier &field) {} + virtual void visit (HIR::StructExprFieldIdentifierValue &field) {} + virtual void visit (HIR::StructExprFieldIndexValue &field) {} + virtual void visit (HIR::StructExprStructFields &expr) {} + virtual void visit (HIR::StructExprStructBase &expr) {} + virtual void visit (HIR::StructExprTuple &expr) {} + virtual void visit (HIR::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (HIR::EnumExprFieldIdentifier &field) {} + virtual void visit (HIR::EnumExprFieldIdentifierValue &field) {} + virtual void visit (HIR::EnumExprFieldIndexValue &field) {} + virtual void visit (HIR::EnumExprStruct &expr) {} + virtual void visit (HIR::EnumExprTuple &expr) {} + virtual void visit (HIR::EnumExprFieldless &expr) {} + virtual void visit (HIR::CallExpr &expr) {} + virtual void visit (HIR::MethodCallExpr &expr) {} + virtual void visit (HIR::FieldAccessExpr &expr) {} + virtual void visit (HIR::ClosureExprInner &expr) {} + virtual void visit (HIR::BlockExpr &expr) {} + virtual void visit (HIR::ClosureExprInnerTyped &expr) {} + virtual void visit (HIR::ContinueExpr &expr) {} + virtual void visit (HIR::BreakExpr &expr) {} + virtual void visit (HIR::RangeFromToExpr &expr) {} + virtual void visit (HIR::RangeFromExpr &expr) {} + virtual void visit (HIR::RangeToExpr &expr) {} + virtual void visit (HIR::RangeFullExpr &expr) {} + virtual void visit (HIR::RangeFromToInclExpr &expr) {} + virtual void visit (HIR::RangeToInclExpr &expr) {} + virtual void visit (HIR::ReturnExpr &expr) {} + virtual void visit (HIR::UnsafeBlockExpr &expr) {} + virtual void visit (HIR::LoopExpr &expr) {} + virtual void visit (HIR::WhileLoopExpr &expr) {} + virtual void visit (HIR::WhileLetLoopExpr &expr) {} + virtual void visit (HIR::ForLoopExpr &expr) {} + virtual void visit (HIR::IfExpr &expr) {} + virtual void visit (HIR::IfExprConseqElse &expr) {} + virtual void visit (HIR::IfExprConseqIf &expr) {} + virtual void visit (HIR::IfExprConseqIfLet &expr) {} + virtual void visit (HIR::IfLetExpr &expr) {} + virtual void visit (HIR::IfLetExprConseqElse &expr) {} + virtual void visit (HIR::IfLetExprConseqIf &expr) {} + virtual void visit (HIR::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (HIR::MatchCaseBlockExpr &match_case) {} + // virtual void visit (HIR::MatchCaseExpr &match_case) {} + virtual void visit (HIR::MatchExpr &expr) {} + virtual void visit (HIR::AwaitExpr &expr) {} + virtual void visit (HIR::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (HIR::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (HIR::LifetimeWhereClauseItem &item) {} + virtual void visit (HIR::TypeBoundWhereClauseItem &item) {} + virtual void visit (HIR::Method &method) {} + virtual void visit (HIR::ModuleBodied &module) {} + virtual void visit (HIR::ModuleNoBody &module) {} + virtual void visit (HIR::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (HIR::UseTreeGlob &use_tree) {} + virtual void visit (HIR::UseTreeList &use_tree) {} + virtual void visit (HIR::UseTreeRebind &use_tree) {} + virtual void visit (HIR::UseDeclaration &use_decl) {} + virtual void visit (HIR::Function &function) {} + virtual void visit (HIR::TypeAlias &type_alias) {} + virtual void visit (HIR::StructStruct &struct_item) {} + virtual void visit (HIR::TupleStruct &tuple_struct) {} + virtual void visit (HIR::EnumItem &item) {} + virtual void visit (HIR::EnumItemTuple &item) {} + virtual void visit (HIR::EnumItemStruct &item) {} + virtual void visit (HIR::EnumItemDiscriminant &item) {} + virtual void visit (HIR::Enum &enum_item) {} + virtual void visit (HIR::Union &union_item) {} + virtual void visit (HIR::ConstantItem &const_item) {} + virtual void visit (HIR::StaticItem &static_item) {} + virtual void visit (HIR::TraitItemFunc &item) {} + virtual void visit (HIR::TraitItemMethod &item) {} + virtual void visit (HIR::TraitItemConst &item) {} + virtual void visit (HIR::TraitItemType &item) {} + virtual void visit (HIR::Trait &trait) {} + virtual void visit (HIR::InherentImpl &impl) {} + virtual void visit (HIR::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (HIR::ExternalStaticItem &item) {} + virtual void visit (HIR::ExternalFunctionItem &item) {} + virtual void visit (HIR::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (HIR::MacroMatchFragment &match) {} + virtual void visit (HIR::MacroMatchRepetition &match) {} + virtual void visit (HIR::MacroMatcher &matcher) {} + virtual void visit (HIR::MacroRulesDefinition &rules_def) {} + virtual void visit (HIR::MacroInvocation ¯o_invoc) {} + virtual void visit (HIR::MetaItemPath &meta_item) {} + virtual void visit (HIR::MetaItemSeq &meta_item) {} + virtual void visit (HIR::MetaWord &meta_item) {} + virtual void visit (HIR::MetaNameValueStr &meta_item) {} + virtual void visit (HIR::MetaListPaths &meta_item) {} + virtual void visit (HIR::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (HIR::LiteralPattern &pattern) {} + virtual void visit (HIR::IdentifierPattern &pattern) {} + virtual void visit (HIR::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (HIR::RangePatternBoundLiteral &bound) {} + virtual void visit (HIR::RangePatternBoundPath &bound) {} + virtual void visit (HIR::RangePatternBoundQualPath &bound) {} + virtual void visit (HIR::RangePattern &pattern) {} + virtual void visit (HIR::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (HIR::StructPatternFieldTuplePat &field) {} + virtual void visit (HIR::StructPatternFieldIdentPat &field) {} + virtual void visit (HIR::StructPatternFieldIdent &field) {} + virtual void visit (HIR::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (HIR::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (HIR::TupleStructItemsRange &tuple_items) {} + virtual void visit (HIR::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (HIR::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (HIR::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (HIR::TuplePattern &pattern) {} + virtual void visit (HIR::GroupedPattern &pattern) {} + virtual void visit (HIR::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (HIR::EmptyStmt &stmt) {} + virtual void visit (HIR::LetStmt &stmt) {} + virtual void visit (HIR::ExprStmtWithoutBlock &stmt) {} + virtual void visit (HIR::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (HIR::TraitBound &bound) {} + virtual void visit (HIR::ImplTraitType &type) {} + virtual void visit (HIR::TraitObjectType &type) {} + virtual void visit (HIR::ParenthesisedType &type) {} + virtual void visit (HIR::ImplTraitTypeOneBound &type) {} + virtual void visit (HIR::TraitObjectTypeOneBound &type) {} + virtual void visit (HIR::TupleType &type) {} + virtual void visit (HIR::NeverType &type) {} + virtual void visit (HIR::RawPointerType &type) {} + virtual void visit (HIR::ReferenceType &type) {} + virtual void visit (HIR::ArrayType &type) {} + virtual void visit (HIR::SliceType &type) {} + virtual void visit (HIR::InferredType &type) {} + virtual void visit (HIR::BareFunctionType &type) {} + +protected: + TypeCheckBase () + : mappings (Analysis::Mappings::get ()), resolver (Resolver::get ()), + context (TypeCheckContext::get ()) + {} + + Analysis::Mappings *mappings; + Resolver *resolver; + TypeCheckContext *context; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_BASE diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h new file mode 100644 index 0000000..32a5d8b --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -0,0 +1,188 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_EXPR +#define RUST_HIR_TYPE_CHECK_EXPR + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-tyty.h" +#include "rust-tyty-call.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckExpr : public TypeCheckBase +{ +public: + static TyTy::TyBase *Resolve (HIR::Expr *expr) + { + TypeCheckExpr resolver; + expr->accept_vis (resolver); + if (resolver.infered != nullptr) + resolver.context->insert_type (expr->get_mappings ().get_hirid (), + resolver.infered); + + return resolver.infered; + } + + void visit (HIR::ReturnExpr &expr) + { + auto ret = context->peek_return_type (); + rust_assert (ret != nullptr); + + auto expr_ty = TypeCheckExpr::Resolve (expr.get_expr ()); + infered = ret->combine (expr_ty); + } + + void visit (HIR::CallExpr &expr) + { + auto fn = expr.get_fnexpr (); + auto fn_node_id = fn->get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id; + if (!resolver->lookup_resolved_name (fn_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup reference for node: %s", + expr.as_string ().c_str ()); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), + ref_node_id, &ref)) + { + rust_error_at (expr.get_locus (), "reverse lookup failure"); + return; + } + + // check if this has a type + TyTy::TyBase *lookup; + if (!context->lookup_type (ref, &lookup)) + { + // FIXME we need to be able to lookup the location info for the + // reference here + rust_error_at (expr.get_locus (), "consider giving this a type: %s", + expr.as_string ().c_str ()); + return; + } + + infered = TyTy::TypeCheckCallExpr::go (lookup, expr); + } + + void visit (HIR::AssignmentExpr &expr) + { + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + + infered = lhs->combine (rhs); + } + + void visit (HIR::IdentifierExpr &expr) + { + NodeId ast_node_id = expr.get_mappings ().get_nodeid (); + + // then lookup the reference_node_id + NodeId ref_node_id; + if (!resolver->lookup_resolved_name (ast_node_id, &ref_node_id)) + { + rust_error_at (expr.get_locus (), + "Failed to lookup reference for node: %s", + expr.as_string ().c_str ()); + return; + } + + // these ref_node_ids will resolve to a pattern declaration but we are + // interested in the definition that this refers to get the parent id + Definition def; + if (!resolver->lookup_definition (ref_node_id, &def)) + { + rust_error_at (expr.get_locus (), "unknown reference"); + return; + } + + // node back to HIR + HirId ref; + if (!mappings->lookup_node_to_hir (expr.get_mappings ().get_crate_num (), + def.parent, &ref)) + { + rust_error_at (expr.get_locus (), "reverse lookup failure"); + return; + } + + // the base reference for this name _must_ have a type set + TyTy::TyBase *lookup; + if (!context->lookup_type (ref, &lookup)) + { + // FIXME we need to be able to lookup the location info for the + // reference here + rust_error_at (expr.get_locus (), "consider giving this a type: %s", + expr.as_string ().c_str ()); + return; + } + + // FIXME this needs to be cloned for memory management later on + infered = lookup; + } + + void visit (HIR::LiteralExpr &expr) + { + switch (expr.get_lit_type ()) + { + case HIR::Literal::LitType::INT: { + // FIXME: + // assume i32 let the combiner functions figure it out + // this should look at the suffix of the literal value to check + auto ok = context->lookup_builtin ("i32", &infered); + rust_assert (ok); + } + break; + + case HIR::Literal::LitType::BOOL: { + auto ok = context->lookup_builtin ("bool", &infered); + rust_assert (ok); + } + break; + + default: + gcc_unreachable (); + break; + } + } + + void visit (HIR::ArithmeticOrLogicalExpr &expr) + { + auto lhs = TypeCheckExpr::Resolve (expr.get_lhs ()); + auto rhs = TypeCheckExpr::Resolve (expr.get_rhs ()); + + infered = lhs->combine (rhs); + } + +private: + TypeCheckExpr () : TypeCheckBase (), infered (nullptr) {} + + TyTy::TyBase *infered; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_EXPR diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h new file mode 100644 index 0000000..ab964a9 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -0,0 +1,91 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_ITEM +#define RUST_HIR_TYPE_CHECK_ITEM + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-stmt.h" +#include "rust-tyty-visitor.h" + +namespace Rust { +namespace Resolver { + +class ResolveFnType : public TyTy::TyVisitor +{ +public: + ResolveFnType (TyTy::TyBase *base) : base (base), state (nullptr) {} + + TyTy::TyBase *go () + { + base->accept_vis (*this); + if (state == nullptr) + gcc_unreachable (); + + return state; + } + + void visit (TyTy::FnType &type) override { state = type.return_type (); } + +private: + TyTy::TyBase *base; + TyTy::TyBase *state; +}; + +class TypeCheckItem : public TypeCheckBase +{ +public: + static void Resolve (HIR::Item *item) + { + TypeCheckItem resolver; + item->accept_vis (resolver); + } + + void visit (HIR::Function &function) + { + TyTy::TyBase *fnType; + if (!context->lookup_type (function.get_mappings ().get_hirid (), &fnType)) + { + rust_error_at (function.locus, "failed to lookup function type"); + return; + } + + // need to get the return type from this + ResolveFnType resolve_fn_type (fnType); + context->push_return_type (resolve_fn_type.go ()); + + // walk statements to make sure they are all typed correctly and they match + // up + function.function_body->iterate_stmts ([&] (HIR::Stmt *s) mutable -> bool { + TypeCheckStmt::Resolve (s); + return true; + }); + + context->pop_return_type (); + } + +private: + TypeCheckItem () : TypeCheckBase () {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_ITEM diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h new file mode 100644 index 0000000..ccf1138 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -0,0 +1,91 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_STMT +#define RUST_HIR_TYPE_CHECK_STMT + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-hir-type-check-expr.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckStmt : public TypeCheckBase +{ +public: + static void Resolve (HIR::Stmt *stmt) + { + TypeCheckStmt resolver; + stmt->accept_vis (resolver); + } + + void visit (HIR::ExprStmtWithoutBlock &stmt) + { + TypeCheckExpr::Resolve (stmt.get_expr ()); + } + + void visit (HIR::LetStmt &stmt) + { + TyTy::TyBase *init_expr_ty = nullptr; + if (stmt.has_init_expr ()) + init_expr_ty = TypeCheckExpr::Resolve (stmt.get_init_expr ()); + + TyTy::TyBase *specified_ty = nullptr; + if (stmt.has_type ()) + specified_ty = TypeCheckType::Resolve (stmt.get_type ()); + + // let x:i32 = 123; + if (specified_ty != nullptr && init_expr_ty != nullptr) + { + context->insert_type (stmt.get_mappings ().get_hirid (), + specified_ty->combine (init_expr_ty)); + } + else + { + // let x:i32; + if (specified_ty != nullptr) + { + context->insert_type (stmt.get_mappings ().get_hirid (), + specified_ty); + } + // let x = 123; + else if (init_expr_ty != nullptr) + { + context->insert_type (stmt.get_mappings ().get_hirid (), + init_expr_ty); + } + // let x; + else + { + context->insert_type (stmt.get_mappings ().get_hirid (), + new TyTy::InferType ( + stmt.get_mappings ().get_hirid ())); + } + } + } + +private: + TypeCheckStmt () : TypeCheckBase () {} +}; // namespace Resolver + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_STMT diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h new file mode 100644 index 0000000..25e6c0b --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -0,0 +1,72 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_TOPLEVEL +#define RUST_HIR_TYPE_CHECK_TOPLEVEL + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-type.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckTopLevel : public TypeCheckBase +{ +public: + static void Resolve (HIR::Item *item) + { + TypeCheckTopLevel resolver; + item->accept_vis (resolver); + } + + void visit (HIR::Function &function) + { + TyTy::TyBase *ret_type = nullptr; + if (!function.has_function_return_type ()) + ret_type = new TyTy::UnitType (function.get_mappings ().get_hirid ()); + else + ret_type = TypeCheckType::Resolve (function.return_type.get ()); + + std::vector<TyTy::ParamType *> params; + for (auto ¶m : function.function_params) + { + // get the name as well required for later on + auto param_type = TypeCheckType::Resolve (param.type.get ()); + auto param_tyty + = new TyTy::ParamType (param.get_mappings ()->get_hirid (), + param.param_name->as_string (), param_type); + params.push_back (param_tyty); + + context->insert_type (param.get_mappings ()->get_hirid (), param_tyty); + } + + auto fnType = new TyTy::FnType (function.get_mappings ().get_hirid (), + params, ret_type); + context->insert_type (function.get_mappings ().get_hirid (), fnType); + } + +private: + TypeCheckTopLevel () : TypeCheckBase () {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_TOPLEVEL diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h new file mode 100644 index 0000000..beab77a --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -0,0 +1,82 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK_TYPE +#define RUST_HIR_TYPE_CHECK_TYPE + +#include "rust-hir-type-check-base.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckType : public TypeCheckBase +{ +public: + static TyTy::TyBase *Resolve (HIR::Type *type) + { + TypeCheckType resolver; + type->accept_vis (resolver); + + if (resolver.translated != nullptr) + resolver.context->insert_type (type->get_mappings ().get_hirid (), + resolver.translated); + + return resolver.translated; + } + + virtual void visit (HIR::TypePath &path) + { + // check if this is already defined or not + if (context->lookup_type (path.get_mappings ().get_hirid (), &translated)) + return; + + // lookup the Node this resolves to + NodeId ref; + if (!resolver->lookup_resolved_type (path.get_mappings ().get_nodeid (), + &ref)) + { + rust_error_at (path.get_locus (), "Type was not resolved"); + return; + } + + // reverse lookup the hir node from ast node id + HirId hir_lookup; + if (context->lookup_type_by_node_id (ref, &hir_lookup)) + { + // we got an HIR node + if (context->lookup_type (hir_lookup, &translated)) + return; + } + + // this might be a struct type (TyTy::ADT) reference + // TODO + printf ("UNREACHABLE %s\n", path.as_string ().c_str ()); + gcc_unreachable (); + } + +private: + TypeCheckType () : TypeCheckBase (), translated (nullptr) {} + + TyTy::TyBase *translated; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_TYPE diff --git a/gcc/rust/typecheck/rust-hir-type-check.cc b/gcc/rust/typecheck/rust-hir-type-check.cc new file mode 100644 index 0000000..f9dbe49 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check.cc @@ -0,0 +1,38 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-hir-type-check.h" +#include "rust-hir-full.h" +#include "rust-hir-type-check-toplevel.h" +#include "rust-hir-type-check-item.h" + +namespace Rust { +namespace Resolver { + +void +TypeResolution::Resolve (HIR::Crate &crate) +{ + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + TypeCheckTopLevel::Resolve (it->get ()); + + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + TypeCheckItem::Resolve (it->get ()); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h new file mode 100644 index 0000000..6deecdd --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -0,0 +1,67 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_TYPE_CHECK +#define RUST_HIR_TYPE_CHECK + +#include "rust-hir-full-decls.h" +#include "rust-hir-map.h" +#include "rust-tyty.h" + +namespace Rust { +namespace Resolver { + +class TypeCheckContext +{ +public: + static TypeCheckContext *get (); + + ~TypeCheckContext (); + + bool lookup_builtin (std::string name, TyTy::TyBase **type); + void insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type); + + void insert_type (HirId id, TyTy::TyBase *type); + bool lookup_type (HirId id, TyTy::TyBase **type); + + void insert_type_by_node_id (NodeId ref, HirId id); + bool lookup_type_by_node_id (NodeId ref, HirId *id); + + TyTy::TyBase *peek_return_type (); + void push_return_type (TyTy::TyBase *return_type); + void pop_return_type (); + +private: + TypeCheckContext (); + + std::map<NodeId, HirId> node_id_refs; + std::map<HirId, TyTy::TyBase *> resolved; + std::vector<std::unique_ptr<TyTy::TyBase> > builtins; + std::vector<TyTy::TyBase *> return_type_stack; +}; + +class TypeResolution +{ +public: + static void Resolve (HIR::Crate &crate); +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc new file mode 100644 index 0000000..8869e34 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -0,0 +1,116 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-hir-type-check.h" + +namespace Rust { +namespace Resolver { + +TypeCheckContext * +TypeCheckContext::get () +{ + static TypeCheckContext *instance; + if (instance == nullptr) + instance = new TypeCheckContext (); + + return instance; +} + +TypeCheckContext::TypeCheckContext () {} + +TypeCheckContext::~TypeCheckContext () {} + +bool +TypeCheckContext::lookup_builtin (std::string name, TyTy::TyBase **type) +{ + for (auto &builtin : builtins) + { + if (name.compare (builtin->as_string ()) == 0) + { + *type = builtin.get (); + return true; + } + } + return false; +} + +void +TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type) +{ + node_id_refs[ref] = id; + resolved[id] = type; + builtins.push_back (std::unique_ptr<TyTy::TyBase> (type)); +} + +void +TypeCheckContext::insert_type (HirId id, TyTy::TyBase *type) +{ + rust_assert (resolved.find (id) == resolved.end ()); + rust_assert (type != nullptr); + resolved[id] = type; +} + +bool +TypeCheckContext::lookup_type (HirId id, TyTy::TyBase **type) +{ + auto it = resolved.find (id); + if (it == resolved.end ()) + return false; + + *type = it->second; + return true; +} + +void +TypeCheckContext::insert_type_by_node_id (NodeId ref, HirId id) +{ + rust_assert (node_id_refs.find (ref) == node_id_refs.end ()); + node_id_refs[ref] = id; +} + +bool +TypeCheckContext::lookup_type_by_node_id (NodeId ref, HirId *id) +{ + auto it = node_id_refs.find (ref); + if (it == node_id_refs.end ()) + return false; + + *id = it->second; + return true; +} + +TyTy::TyBase * +TypeCheckContext::peek_return_type () +{ + return return_type_stack.back (); +} + +void +TypeCheckContext::push_return_type (TyTy::TyBase *return_type) +{ + return_type_stack.push_back (return_type); +} + +void +TypeCheckContext::pop_return_type () +{ + return_type_stack.pop_back (); +} + +} // namespace Resolver +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty-call.h b/gcc/rust/typecheck/rust-tyty-call.h new file mode 100644 index 0000000..d1341df --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-call.h @@ -0,0 +1,53 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_TYTY_CALL +#define RUST_TYTY_CALL + +#include "rust-diagnostics.h" +#include "rust-hir-full.h" +#include "rust-tyty-visitor.h" +#include "rust-tyty.h" + +namespace Rust { +namespace TyTy { + +class TypeCheckCallExpr : private TyVisitor +{ +public: + static TyBase *go (TyBase *ref, HIR::CallExpr &call) + { + TypeCheckCallExpr checker (call); + ref->accept_vis (checker); + return checker.resolved; + } + ~TypeCheckCallExpr () {} + + void visit (FnType &type) override; + +private: + TypeCheckCallExpr (HIR::CallExpr &c) : resolved (nullptr), call (c) {} + + TyBase *resolved; + HIR::CallExpr &call; +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY_CALL diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h new file mode 100644 index 0000000..372229b --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -0,0 +1,241 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_TYTY_RULES +#define RUST_TYTY_RULES + +#include "rust-diagnostics.h" +#include "rust-tyty.h" +#include "rust-tyty-visitor.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace TyTy { + +class BaseRules : public TyVisitor +{ +public: + virtual ~BaseRules () {} + + virtual void visit (UnitType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (InferType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (FnType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (ParamType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (BoolType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (IntType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + + virtual void visit (UintType &type) override + { + Location locus = mappings->lookup_location (type.get_ref ()); + rust_error_at (locus, "expected [%s] got [%s]", base->as_string ().c_str (), + type.as_string ().c_str ()); + } + +protected: + BaseRules (TyBase *base) : mappings (Analysis::Mappings::get ()), base (base) + {} + + Analysis::Mappings *mappings; + +private: + TyBase *base; +}; + +class InferRules : protected BaseRules +{ +public: + InferRules (InferType *base) + : BaseRules (base), base (base), resolved (nullptr) + {} + ~InferRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + +private: + InferType *base; + TyBase *resolved; +}; + +class UnitRules : protected BaseRules +{ +public: + UnitRules (UnitType *base) : BaseRules (base), base (base), resolved (nullptr) + {} + ~UnitRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + +private: + UnitType *base; + TyBase *resolved; +}; + +class FnRules : protected BaseRules +{ +public: + FnRules (FnType *base) : BaseRules (base), base (base), resolved (nullptr) {} + ~FnRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + +private: + FnType *base; + TyBase *resolved; +}; + +class ParamRules : protected BaseRules +{ +public: + ParamRules (ParamType *base) + : BaseRules (base), base (base), resolved (nullptr) + {} + ~ParamRules () {} + + TyBase *combine (TyBase *other) + { + // we only case about the base type of a param + return base->get_base_type ()->combine (other); + } + +private: + ParamType *base; + TyBase *resolved; +}; + +class BoolRules : protected BaseRules +{ +public: + BoolRules (BoolType *base) : BaseRules (base), base (base), resolved (nullptr) + {} + ~BoolRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + + void visit (BoolType &type) override + { + resolved = new BoolType (type.get_ref ()); + } + +private: + BoolType *base; + TyBase *resolved; +}; + +class IntRules : protected BaseRules +{ +public: + IntRules (IntType *base) : BaseRules (base), base (base), resolved (nullptr) + {} + ~IntRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + + void visit (IntType &type) override + { + // FIXME we should look at the IntTypeKind and check if i8 vs i16 etc.. + resolved = new IntType (type.get_ref (), type.get_kind ()); + } + +private: + IntType *base; + TyBase *resolved; +}; + +class UintRules : protected BaseRules +{ +public: + UintRules (UintType *base) : BaseRules (base), base (base), resolved (nullptr) + {} + ~UintRules () {} + + TyBase *combine (TyBase *other) + { + other->accept_vis (*this); + return resolved; + } + + void visit (UintType &type) override + { + // FIXME we should look at the IntTypeKind and check if u8 vs u16 etc.. + resolved = new UintType (type.get_ref (), type.get_kind ()); + } + +private: + UintType *base; + TyBase *resolved; +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY_RULES diff --git a/gcc/rust/typecheck/rust-tyty-visitor.h b/gcc/rust/typecheck/rust-tyty-visitor.h new file mode 100644 index 0000000..68a8a43 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty-visitor.h @@ -0,0 +1,42 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_TYTY_VISITOR +#define RUST_TYTY_VISITOR + +#include "rust-tyty.h" + +namespace Rust { +namespace TyTy { + +class TyVisitor +{ +public: + virtual void visit (UnitType &type) {} + virtual void visit (InferType &type) {} + virtual void visit (FnType &type) {} + virtual void visit (ParamType &type) {} + virtual void visit (BoolType &type) {} + virtual void visit (IntType &type) {} + virtual void visit (UintType &type) {} +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY_VISITOR diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc new file mode 100644 index 0000000..4a36d4f --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -0,0 +1,223 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-tyty.h" +#include "rust-tyty-visitor.h" +#include "rust-tyty-call.h" +#include "rust-hir-type-check-expr.h" +#include "rust-tyty-rules.h" + +namespace Rust { +namespace TyTy { + +void +UnitType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +UnitType::as_string () const +{ + return "()"; +} + +TyBase * +UnitType::combine (TyBase *other) +{ + UnitRules r (this); + return r.combine (other); +} + +void +InferType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +InferType::as_string () const +{ + return "[_]"; +} + +TyBase * +InferType::combine (TyBase *other) +{ + InferRules r (this); + return r.combine (other); +} + +void +FnType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +FnType::as_string () const +{ + std::string params_str = ""; + for (auto ¶m : params) + { + params_str += param->as_string (); + params_str += ","; + } + + std::string ret_str = type->as_string (); + return "fn (" + params_str + ") -> " + ret_str; +} + +TyBase * +FnType::combine (TyBase *other) +{ + FnRules r (this); + return r.combine (other); +} + +void +ParamType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +ParamType::as_string () const +{ + return "(" + identifier + " :" + type->as_string () + ")"; +} + +TyBase * +ParamType::combine (TyBase *other) +{ + ParamRules r (this); + return r.combine (other); +} + +void +BoolType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +BoolType::as_string () const +{ + return "bool"; +} + +TyBase * +BoolType::combine (TyBase *other) +{ + BoolRules r (this); + return r.combine (other); +} + +void +IntType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +IntType::as_string () const +{ + switch (int_kind) + { + case I8: + return "i8"; + case I16: + return "i16"; + case I32: + return "i32"; + } + gcc_unreachable (); + return "__unknown_int_type"; +} + +TyBase * +IntType::combine (TyBase *other) +{ + IntRules r (this); + return r.combine (other); +} + +void +UintType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +UintType::as_string () const +{ + switch (uint_kind) + { + case U8: + return "u8"; + case U16: + return "u16"; + case U32: + return "u32"; + } + gcc_unreachable (); + return "__unknown_uint_type"; +} + +TyBase * +UintType::combine (TyBase *other) +{ + UintRules r (this); + return r.combine (other); +} + +void +TypeCheckCallExpr::visit (FnType &type) +{ + if (call.num_params () != type.num_params ()) + { + rust_error_at (call.get_locus (), "differing number of arguments"); + return; + } + + size_t i = 0; + call.iterate_params ([&] (HIR::Expr *p) mutable -> bool { + TyBase *pt = type.param_at (i); + auto t = Resolver::TypeCheckExpr::Resolve (p); + if (t == nullptr) + { + rust_error_at (p->get_locus_slow (), "failed to resolve type"); + return false; + } + + auto res = pt->combine (t); + if (res == nullptr) + return false; + + i++; + return true; + }); + + if (i != call.num_params ()) + return; + + resolved = type.get_return_type (); +} + +} // namespace TyTy +} // namespace Rust diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h new file mode 100644 index 0000000..4e04490 --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty.h @@ -0,0 +1,213 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_TYTY +#define RUST_TYTY + +#include "rust-hir-map.h" + +namespace Rust { +namespace TyTy { + +// https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.TyKind.html#variants +enum TypeKind +{ + INFER, + ADT, + STR, + REF, + PARAM, + ARRAY, + FNDEF, + TUPLE, + BOOL, + CHAR, + INT, + UINT, + FLOAT, + UNIT, + // there are more to add... +}; + +class TyVisitor; +class TyBase +{ +public: + ~TyBase () {} + + HirId get_ref () const { return ref; } + + virtual void accept_vis (TyVisitor &vis) = 0; + + virtual std::string as_string () const = 0; + + virtual TyBase *combine (TyBase *other) = 0; + + virtual bool is_unit () const { return kind == TypeKind::UNIT; } + +protected: + TyBase (HirId ref, TypeKind kind) : kind (kind), ref (ref) {} + + TypeKind kind; + HirId ref; +}; + +class InferType : public TyBase +{ +public: + InferType (HirId ref) : TyBase (ref, TypeKind::INFER) {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return true; } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; +}; + +class UnitType : public TyBase +{ +public: + UnitType (HirId ref) : TyBase (ref, TypeKind::UNIT) {} + + void accept_vis (TyVisitor &vis) override; + + bool is_unit () const override { return true; } + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; +}; + +class ParamType : public TyBase +{ +public: + ParamType (HirId ref, std::string identifier, TyBase *type) + : TyBase (ref, TypeKind::PARAM), identifier (identifier), type (type) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + std::string get_identifier () const { return identifier; } + + TyBase *get_base_type () { return type; } + +private: + std::string identifier; + TyBase *type; +}; + +class FnType : public TyBase +{ +public: + FnType (HirId ref, std::vector<ParamType *> params, TyBase *type) + : TyBase (ref, TypeKind::FNDEF), params (params), type (type) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *return_type () { return type; } + + TyBase *combine (TyBase *other) override; + + size_t num_params () const { return params.size (); } + + ParamType *param_at (size_t idx) { return params[idx]; } + + TyBase *get_return_type () { return type; } + +private: + std::vector<ParamType *> params; + TyBase *type; +}; + +class BoolType : public TyBase +{ +public: + BoolType (HirId ref) : TyBase (ref, TypeKind::BOOL) {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; +}; + +class IntType : public TyBase +{ +public: + enum IntKind + { + I8, + I16, + I32, + }; + + IntType (HirId ref, IntKind kind) + : TyBase (ref, TypeKind::INT), int_kind (kind) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + IntKind get_kind () const { return int_kind; } + +private: + IntKind int_kind; +}; + +class UintType : public TyBase +{ +public: + enum UintKind + { + U8, + U16, + U32, + }; + + UintType (HirId ref, UintKind kind) + : TyBase (ref, TypeKind::UINT), uint_kind (kind) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + + UintKind get_kind () const { return uint_kind; } + +private: + UintKind uint_kind; +}; + +} // namespace TyTy +} // namespace Rust + +#endif // RUST_TYTY diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc new file mode 100644 index 0000000..bdf487e --- /dev/null +++ b/gcc/rust/util/rust-hir-map.cc @@ -0,0 +1,447 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#include "rust-hir-map.h" +#include "rust-ast-full.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace Analysis { + +NodeMapping::NodeMapping (CrateNum crateNum, NodeId nodeId, HirId hirId, + LocalDefId localDefId) + : crateNum (crateNum), nodeId (nodeId), hirId (hirId), localDefId (localDefId) +{} + +NodeMapping::~NodeMapping () {} + +NodeMapping +NodeMapping::get_error () +{ + return NodeMapping (UNKNOWN_CREATENUM, UNKNOWN_NODEID, UNKNOWN_HIRID, + UNKNOWN_LOCAL_DEFID); +} + +CrateNum +NodeMapping::get_crate_num () const +{ + return crateNum; +} + +NodeId +NodeMapping::get_nodeid () const +{ + return nodeId; +} + +HirId +NodeMapping::get_hirid () const +{ + return hirId; +} + +LocalDefId +NodeMapping::get_local_defid () const +{ + return localDefId; +} + +DefId +NodeMapping::get_defid () const +{ + return get_defid (get_crate_num (), get_local_defid ()); +} + +DefId +NodeMapping::get_defid (CrateNum crate_num, LocalDefId local_defid) +{ + DefId val = 0; + val |= crate_num; + val = val << sizeof (uint32_t); + val |= local_defid; + return val; +} + +std::string +NodeMapping::as_string () const +{ + std::ostringstream ss; + ss << "[" + << "C: " << get_crate_num (); + if (get_nodeid () != UNKNOWN_NODEID) + ss << " Nid: " << get_nodeid (); + + if (get_hirid () != UNKNOWN_HIRID) + ss << " Hid: " << get_hirid (); + + if (get_local_defid () != UNKNOWN_LOCAL_DEFID) + ss << " Lid: " << get_local_defid (); + + ss << "]"; + return ss.str (); +} + +// Mappings Class now + +Mappings::Mappings () {} + +Mappings::~Mappings () {} + +Mappings * +Mappings::get () +{ + static std::unique_ptr<Mappings> instance; + if (!instance) + instance = std::move (std::unique_ptr<Mappings> (new Mappings ())); + + return instance.get (); +} + +CrateNum +Mappings::get_next_crate_num () +{ + return crateNumItr++; +} + +void +Mappings::set_current_crate (CrateNum crateNum) +{ + currentCrateNum = crateNum; +} + +CrateNum +Mappings::get_current_crate () +{ + // HACK + if (hirIdIter.find (currentCrateNum) == hirIdIter.end ()) + { + hirIdIter[currentCrateNum] = UNKNOWN_HIRID; + nodeIdIter[currentCrateNum] = UNKNOWN_NODEID; + localIdIter[currentCrateNum] = UNKNOWN_LOCAL_DEFID; + nodeIdToHirMappings[currentCrateNum] = {}; + locations[currentCrateNum] = {}; + } + + return currentCrateNum; +} + +NodeId +Mappings::get_next_node_id (CrateNum crateNum) +{ + auto it = nodeIdIter.find (crateNum); + rust_assert (it != nodeIdIter.end ()); + + auto id = it->second + 1; + nodeIdIter[crateNum] = id; + return id; +} + +HirId +Mappings::get_next_hir_id (CrateNum crateNum) +{ + auto it = hirIdIter.find (crateNum); + rust_assert (it != hirIdIter.end ()); + + auto id = it->second + 1; + hirIdIter[crateNum] = id; + return id; +} + +LocalDefId +Mappings::get_next_localdef_id (CrateNum crateNum) +{ + auto it = localIdIter.find (crateNum); + rust_assert (it != localIdIter.end ()); + + auto id = it->second + 1; + localIdIter[crateNum] = id; + return id; +} + +AST::Crate * +Mappings::get_ast_crate (CrateNum crateNum) +{ + auto it = astCrateMappings.find (crateNum); + if (it == astCrateMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_ast_crate (AST::Crate *crate) +{ + CrateNum crateNum = get_current_crate (); + rust_assert (get_ast_crate (crateNum) == nullptr); + + astCrateMappings[crateNum] = crate; +} + +HIR::Crate * +Mappings::get_hir_crate (CrateNum crateNum) +{ + auto it = hirCrateMappings.find (crateNum); + if (it == hirCrateMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_crate (HIR::Crate *crate) +{ + CrateNum crateNum = crate->get_mappings ().get_crate_num (); + rust_assert (get_hir_crate (crateNum) == nullptr); + + hirCrateMappings[crateNum] = crate; +} + +void +Mappings::insert_defid_mapping (DefId id, HIR::Item *item) +{ + CrateNum crateNum = (id & DEF_ID_CRATE_MASK) >> sizeof (uint32_t); + LocalDefId localDefId = id & DEF_ID_LOCAL_DEF_MASK; + + rust_assert (lookup_defid (id) == nullptr); + rust_assert (lookup_local_defid (crateNum, localDefId) == nullptr); + + defIdMappings[id] = item; + insert_local_defid_mapping (crateNum, localDefId, item); +} + +HIR::Item * +Mappings::lookup_defid (DefId id) +{ + auto it = defIdMappings.find (id); + if (it == defIdMappings.end ()) + return nullptr; + + return it->second; +} + +void +Mappings::insert_hir_item (CrateNum crateNum, HirId id, HIR::Item *item) +{ + rust_assert (lookup_hir_item (crateNum, id) == nullptr); + + hirItemMappings[crateNum][id] = item; + nodeIdToHirMappings[crateNum][item->get_mappings ().get_nodeid ()] = id; +} + +HIR::Item * +Mappings::lookup_hir_item (CrateNum crateNum, HirId id) +{ + auto it = hirItemMappings.find (crateNum); + if (it == hirItemMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void +Mappings::insert_hir_expr (CrateNum crateNum, HirId id, HIR::Expr *expr) +{ + rust_assert (lookup_hir_expr (crateNum, id) == nullptr); + + hirExprMappings[crateNum][id] = expr; + nodeIdToHirMappings[crateNum][expr->get_mappings ().get_nodeid ()] = id; + insert_location (crateNum, id, expr->get_locus_slow ()); +} + +HIR::Expr * +Mappings::lookup_hir_expr (CrateNum crateNum, HirId id) +{ + auto it = hirExprMappings.find (crateNum); + if (it == hirExprMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void +Mappings::insert_hir_type (CrateNum crateNum, HirId id, HIR::Type *type) +{ + rust_assert (lookup_hir_type (crateNum, id) == nullptr); + + hirTypeMappings[crateNum][id] = type; + nodeIdToHirMappings[crateNum][type->get_mappings ().get_nodeid ()] = id; +} + +HIR::Type * +Mappings::lookup_hir_type (CrateNum crateNum, HirId id) +{ + auto it = hirTypeMappings.find (crateNum); + if (it == hirTypeMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void +Mappings::insert_hir_stmt (CrateNum crateNum, HirId id, HIR::Stmt *type) +{ + rust_assert (lookup_hir_stmt (crateNum, id) == nullptr); + + hirStmtMappings[crateNum][id] = type; + nodeIdToHirMappings[crateNum][type->get_mappings ().get_nodeid ()] = id; +} + +HIR::Stmt * +Mappings::lookup_hir_stmt (CrateNum crateNum, HirId id) +{ + auto it = hirStmtMappings.find (crateNum); + if (it == hirStmtMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void +Mappings::insert_hir_param (CrateNum crateNum, HirId id, + HIR::FunctionParam *param) +{ + rust_assert (lookup_hir_stmt (crateNum, id) == nullptr); + + printf ("inserting param with node id %u hir id: %u\n", + param->get_mappings ()->get_nodeid (), id); + hirParamMappings[crateNum][id] = param; + nodeIdToHirMappings[crateNum][param->get_mappings ()->get_nodeid ()] = id; +} + +HIR::FunctionParam * +Mappings::lookup_hir_param (CrateNum crateNum, HirId id) +{ + auto it = hirParamMappings.find (crateNum); + if (it == hirParamMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void +Mappings::insert_local_defid_mapping (CrateNum crateNum, LocalDefId id, + HIR::Item *item) +{ + rust_assert (lookup_local_defid (crateNum, id) == nullptr); + + localDefIdMappings[crateNum][id] = item; +} + +HIR::Item * +Mappings::lookup_local_defid (CrateNum crateNum, LocalDefId id) +{ + auto it = localDefIdMappings.find (crateNum); + if (it == localDefIdMappings.end ()) + return nullptr; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return nullptr; + + return iy->second; +} + +void +Mappings::walk_local_defids_for_crate (CrateNum crateNum, + std::function<bool (HIR::Item *)> cb) +{ + auto it = localDefIdMappings.find (crateNum); + if (it == localDefIdMappings.end ()) + return; + + for (auto iy = it->second.begin (); iy != it->second.end (); iy++) + { + if (!cb (iy->second)) + return; + } +} + +bool +Mappings::lookup_node_to_hir (CrateNum crate, NodeId id, HirId *ref) +{ + auto it = nodeIdToHirMappings.find (crate); + if (it == nodeIdToHirMappings.end ()) + return false; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return false; + + *ref = iy->second; + return true; +} + +void +Mappings::insert_location (CrateNum crate, HirId id, Location locus) +{ + locations[crate][id] = locus; +} + +Location +Mappings::lookup_location (CrateNum crate, HirId id) +{ + auto it = locations.find (crate); + if (it == locations.end ()) + return Location (); + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return Location (); + + return iy->second; +} + +bool +Mappings::resolve_nodeid_to_stmt (CrateNum crate, NodeId id, HIR::Stmt **stmt) +{ + auto it = nodeIdToHirMappings.find (crate); + if (it == nodeIdToHirMappings.end ()) + return false; + + auto iy = it->second.find (id); + if (iy == it->second.end ()) + return false; + + HirId resolved = iy->second; + auto resolved_stmt = lookup_hir_stmt (crate, resolved); + *stmt = resolved_stmt; + return resolved_stmt != nullptr; +} + +} // namespace Analysis +} // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h new file mode 100644 index 0000000..a400265 --- /dev/null +++ b/gcc/rust/util/rust-hir-map.h @@ -0,0 +1,173 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_HIR_MAP_H +#define RUST_HIR_MAP_H + +#include "rust-system.h" +#include "rust-location.h" + +#include "rust-ast-full-decls.h" +#include "rust-hir-full-decls.h" + +namespace Rust { + +// refers to a Crate +typedef uint32_t CrateNum; +// refers to any node in the AST in current Crate +typedef uint32_t NodeId; +// refers to any node in the HIR for the current crate +typedef uint32_t HirId; +// refers to any top-level decl in HIR +typedef uint32_t LocalDefId; +// refers to <Crate><DefId> +typedef uint64_t DefId; + +#define DEF_ID_CRATE_MASK 0xFFFFFFFF00000000 +#define DEF_ID_LOCAL_DEF_MASK 0x00000000FFFFFFFF + +#define UNKNOWN_CREATENUM ((uint32_t) (0)) +#define UNKNOWN_NODEID ((uint32_t) (0)) +#define UNKNOWN_HIRID ((uint32_t) (0)) +#define UNKNOWN_LOCAL_DEFID ((uint32_t) (0)) +#define UNKNOWN_DEFID ((uint64_t) (0)) + +namespace Analysis { + +class NodeMapping +{ +public: + NodeMapping (CrateNum crateNum, NodeId nodeId, HirId hirId, + LocalDefId localDefId); + ~NodeMapping (); + + static NodeMapping get_error (); + + CrateNum get_crate_num () const; + NodeId get_nodeid () const; + HirId get_hirid () const; + LocalDefId get_local_defid () const; + DefId get_defid () const; + + static DefId get_defid (CrateNum crate_num, LocalDefId local_defid); + + std::string as_string () const; + +private: + CrateNum crateNum; + NodeId nodeId; + HirId hirId; + LocalDefId localDefId; +}; + +class Mappings +{ +public: + static Mappings *get (); + ~Mappings (); + + CrateNum get_next_crate_num (); + void set_current_crate (CrateNum crateNum); + CrateNum get_current_crate (); + + NodeId get_next_node_id () { return get_next_node_id (get_current_crate ()); } + NodeId get_next_node_id (CrateNum crateNum); + + HirId get_next_hir_id () { return get_next_hir_id (get_current_crate ()); } + HirId get_next_hir_id (CrateNum crateNum); + + LocalDefId get_next_localdef_id (CrateNum crateNum); + + AST::Crate *get_ast_crate (CrateNum crateNum); + void insert_ast_crate (AST::Crate *crate); + + HIR::Crate *get_hir_crate (CrateNum crateNum); + void insert_hir_crate (HIR::Crate *crate); + + void insert_defid_mapping (DefId id, HIR::Item *item); + HIR::Item *lookup_defid (DefId id); + + void insert_local_defid_mapping (CrateNum crateNum, LocalDefId id, + HIR::Item *item); + HIR::Item *lookup_local_defid (CrateNum crateNum, LocalDefId id); + + void insert_hir_item (CrateNum crateNum, HirId id, HIR::Item *item); + HIR::Item *lookup_hir_item (CrateNum crateNum, HirId id); + + void insert_hir_expr (CrateNum crateNum, HirId id, HIR::Expr *expr); + HIR::Expr *lookup_hir_expr (CrateNum crateNum, HirId id); + + void insert_hir_type (CrateNum crateNum, HirId id, HIR::Type *type); + HIR::Type *lookup_hir_type (CrateNum crateNum, HirId id); + + void insert_hir_stmt (CrateNum crateNum, HirId id, HIR::Stmt *type); + HIR::Stmt *lookup_hir_stmt (CrateNum crateNum, HirId id); + + void insert_hir_param (CrateNum crateNum, HirId id, HIR::FunctionParam *type); + HIR::FunctionParam *lookup_hir_param (CrateNum crateNum, HirId id); + + void walk_local_defids_for_crate (CrateNum crateNum, + std::function<bool (HIR::Item *)> cb); + + bool lookup_node_to_hir (CrateNum crate, NodeId id, HirId *ref); + + void insert_location (CrateNum crate, HirId id, Location locus); + Location lookup_location (CrateNum crate, HirId id); + Location lookup_location (HirId id) + { + return lookup_location (get_current_crate (), id); + } + + bool resolve_nodeid_to_stmt (CrateNum crate, NodeId id, HIR::Stmt **stmt); + bool resolve_nodeid_to_stmt (NodeId id, HIR::Stmt **stmt) + { + return resolve_nodeid_to_stmt (get_current_crate (), id, stmt); + } + +private: + Mappings (); + + CrateNum crateNumItr; + CrateNum currentCrateNum; + + std::map<CrateNum, HirId> hirIdIter; + std::map<CrateNum, NodeId> nodeIdIter; + std::map<CrateNum, LocalDefId> localIdIter; + + std::map<CrateNum, AST::Crate *> astCrateMappings; + std::map<CrateNum, HIR::Crate *> hirCrateMappings; + + std::map<DefId, HIR::Item *> defIdMappings; + std::map<CrateNum, std::map<LocalDefId, HIR::Item *> > localDefIdMappings; + std::map<CrateNum, std::map<HirId, HIR::Item *> > hirItemMappings; + std::map<CrateNum, std::map<HirId, HIR::Type *> > hirTypeMappings; + std::map<CrateNum, std::map<HirId, HIR::Expr *> > hirExprMappings; + std::map<CrateNum, std::map<HirId, HIR::Stmt *> > hirStmtMappings; + std::map<CrateNum, std::map<HirId, HIR::FunctionParam *> > hirParamMappings; + + // location info + std::map<CrateNum, std::map<NodeId, Location> > locations; + + // reverse mappings + std::map<CrateNum, std::map<NodeId, HirId> > nodeIdToHirMappings; +}; + +} // namespace Analysis +} // namespace Rust + +#endif // RUST_HIR_MAP_H |