aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorSimplyTheOther <simplytheother@gmail.com>2020-12-18 21:33:09 +0800
committerSimplyTheOther <simplytheother@gmail.com>2020-12-18 21:33:09 +0800
commitaa283484a3dffedc404653af18f9413775cbc3df (patch)
tree118a5b918c48fba3261731bba0a6b4149209f7d8 /gcc
parentf764eeb8abf1ec50794ddb1f31bc57d025e29a3c (diff)
parentbc14d9a0cd3c67093a9c11ad368c0d28325b21c6 (diff)
downloadgcc-aa283484a3dffedc404653af18f9413775cbc3df.zip
gcc-aa283484a3dffedc404653af18f9413775cbc3df.tar.gz
gcc-aa283484a3dffedc404653af18f9413775cbc3df.tar.bz2
Merge branch 'master' of https://github.com/redbrain/gccrs
Diffstat (limited to 'gcc')
-rw-r--r--gcc/rust/Make-lang.in68
-rw-r--r--gcc/rust/analysis/rust-name-resolution.cc657
-rw-r--r--gcc/rust/analysis/rust-name-resolution.h232
-rw-r--r--gcc/rust/analysis/rust-resolution.cc867
-rw-r--r--gcc/rust/analysis/rust-resolution.h51
-rw-r--r--gcc/rust/analysis/rust-scan.cc593
-rw-r--r--gcc/rust/analysis/rust-scan.h233
-rw-r--r--gcc/rust/analysis/rust-type-resolution.cc1348
-rw-r--r--gcc/rust/analysis/rust-type-resolution.h334
-rw-r--r--gcc/rust/analysis/rust-type-visitor.h261
-rw-r--r--gcc/rust/analysis/scope.h57
-rw-r--r--gcc/rust/ast/rust-ast-full-decls.h528
-rw-r--r--gcc/rust/ast/rust-ast.h67
-rw-r--r--gcc/rust/ast/rust-expr.h36
-rw-r--r--gcc/rust/ast/rust-item.h44
-rw-r--r--gcc/rust/ast/rust-path.h40
-rw-r--r--gcc/rust/ast/rust-pattern.h12
-rw-r--r--gcc/rust/backend/rust-compile-base.h249
-rw-r--r--gcc/rust/backend/rust-compile-context.h247
-rw-r--r--gcc/rust/backend/rust-compile-expr.h285
-rw-r--r--gcc/rust/backend/rust-compile-item.h180
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.cc81
-rw-r--r--gcc/rust/backend/rust-compile-resolve-path.h52
-rw-r--r--gcc/rust/backend/rust-compile-stmt.h85
-rw-r--r--gcc/rust/backend/rust-compile-tyty.h247
-rw-r--r--gcc/rust/backend/rust-compile-var-decl.h69
-rw-r--r--gcc/rust/backend/rust-compile.cc1506
-rw-r--r--gcc/rust/backend/rust-compile.h272
-rw-r--r--gcc/rust/hir/README.md40
-rw-r--r--gcc/rust/hir/rust-ast-lower-base.h251
-rw-r--r--gcc/rust/hir/rust-ast-lower-expr.h242
-rw-r--r--gcc/rust/hir/rust-ast-lower-item.h155
-rw-r--r--gcc/rust/hir/rust-ast-lower-pattern.h58
-rw-r--r--gcc/rust/hir/rust-ast-lower-stmt.h102
-rw-r--r--gcc/rust/hir/rust-ast-lower-type.h91
-rw-r--r--gcc/rust/hir/rust-ast-lower.cc62
-rw-r--r--gcc/rust/hir/rust-ast-lower.h46
-rw-r--r--gcc/rust/hir/tree/rust-hir-cond-compilation.h248
-rw-r--r--gcc/rust/hir/tree/rust-hir-expr.h4504
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-decls.h285
-rw-r--r--gcc/rust/hir/tree/rust-hir-full-test.cc6100
-rw-r--r--gcc/rust/hir/tree/rust-hir-full.h32
-rw-r--r--gcc/rust/hir/tree/rust-hir-item.h3259
-rw-r--r--gcc/rust/hir/tree/rust-hir-macro.h628
-rw-r--r--gcc/rust/hir/tree/rust-hir-path.h845
-rw-r--r--gcc/rust/hir/tree/rust-hir-pattern.h1162
-rw-r--r--gcc/rust/hir/tree/rust-hir-stmt.h240
-rw-r--r--gcc/rust/hir/tree/rust-hir-type.h895
-rw-r--r--gcc/rust/hir/tree/rust-hir-visitor.h244
-rw-r--r--gcc/rust/hir/tree/rust-hir.h1467
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-base.h258
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-expr.h105
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-item.h79
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-pattern.h97
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-stmt.h64
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-toplevel.h54
-rw-r--r--gcc/rust/resolve/rust-ast-resolve-type.h66
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.cc252
-rw-r--r--gcc/rust/resolve/rust-ast-resolve.h50
-rw-r--r--gcc/rust/resolve/rust-name-resolver.h222
-rw-r--r--gcc/rust/rust-session-manager.cc91
-rw-r--r--gcc/rust/rust-session-manager.h38
-rw-r--r--gcc/rust/rust-system.h3
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-base.h256
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-expr.h188
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-item.h91
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-stmt.h91
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-toplevel.h72
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check-type.h82
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.cc38
-rw-r--r--gcc/rust/typecheck/rust-hir-type-check.h67
-rw-r--r--gcc/rust/typecheck/rust-tyctx.cc116
-rw-r--r--gcc/rust/typecheck/rust-tyty-call.h53
-rw-r--r--gcc/rust/typecheck/rust-tyty-rules.h241
-rw-r--r--gcc/rust/typecheck/rust-tyty-visitor.h42
-rw-r--r--gcc/rust/typecheck/rust-tyty.cc223
-rw-r--r--gcc/rust/typecheck/rust-tyty.h213
-rw-r--r--gcc/rust/util/rust-hir-map.cc447
-rw-r--r--gcc/rust/util/rust-hir-map.h173
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 &macro)
-{}
-
-// 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 &param)
-{}
-// 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 &macro_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 &macro) 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 &param) 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 &macro_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 &macro)
-{}
-
-// 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 &param)
-{}
-// 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 &param : 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 &macro_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 &macro)
-{}
-
-// 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 &param)
-{}
-// 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 &macro_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 &macro);
-
- // 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 &param);
- // 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 &macro_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 &macro)
-{}
-
-// 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 &param)
-{}
-// 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 &param : 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 &macro_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 &macro) 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 &param) 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 &macro_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 &macro) 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 &param) 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 &macro_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 &macro) {}
+
+ // 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 &param) {}
+ // 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 &macro_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 &macro)
-{}
-
-// 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 &param : 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 &param)
-{}
-// 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 &param : 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 &param : 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 &macro_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 &macro);
+#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 &param);
- // 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 &macro_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 &macro) {}
+
+ // 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 &param) {}
+ // 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 &macro_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 &param : 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 &param : fn->function_params)
+ {
+ mappings->insert_hir_param (mapping.get_crate_num (),
+ param.get_mappings ()->get_hirid (),
+ &param);
+ 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &param : 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 &macro) = 0;
+
+ // rust-path.h
+ virtual void visit (PathInExpression &path) = 0;
+ virtual void visit (TypePathSegment &segment) = 0;
+ virtual void visit (TypePathSegmentGeneric &segment) = 0;
+ virtual void visit (TypePathSegmentFunction &segment) = 0;
+ virtual void visit (TypePath &path) = 0;
+ virtual void visit (QualifiedPathInExpression &path) = 0;
+ virtual void visit (QualifiedPathInType &path) = 0;
+
+ // rust-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 &param) = 0;
+ // virtual void visit(WhereClauseItem& item) = 0;
+ virtual void visit (LifetimeWhereClauseItem &item) = 0;
+ virtual void visit (TypeBoundWhereClauseItem &item) = 0;
+ virtual void visit (Method &method) = 0;
+ virtual void visit (ModuleBodied &module) = 0;
+ virtual void visit (ModuleNoBody &module) = 0;
+ virtual void visit (ExternCrate &crate) = 0;
+ // virtual void visit(UseTree& use_tree) = 0;
+ virtual void visit (UseTreeGlob &use_tree) = 0;
+ virtual void visit (UseTreeList &use_tree) = 0;
+ virtual void visit (UseTreeRebind &use_tree) = 0;
+ virtual void visit (UseDeclaration &use_decl) = 0;
+ virtual void visit (Function &function) = 0;
+ virtual void visit (TypeAlias &type_alias) = 0;
+ virtual void visit (StructStruct &struct_item) = 0;
+ virtual void visit (TupleStruct &tuple_struct) = 0;
+ virtual void visit (EnumItem &item) = 0;
+ virtual void visit (EnumItemTuple &item) = 0;
+ virtual void visit (EnumItemStruct &item) = 0;
+ virtual void visit (EnumItemDiscriminant &item) = 0;
+ virtual void visit (Enum &enum_item) = 0;
+ virtual void visit (Union &union_item) = 0;
+ virtual void visit (ConstantItem &const_item) = 0;
+ virtual void visit (StaticItem &static_item) = 0;
+ virtual void visit (TraitItemFunc &item) = 0;
+ virtual void visit (TraitItemMethod &item) = 0;
+ virtual void visit (TraitItemConst &item) = 0;
+ virtual void visit (TraitItemType &item) = 0;
+ virtual void visit (Trait &trait) = 0;
+ virtual void visit (InherentImpl &impl) = 0;
+ virtual void visit (TraitImpl &impl) = 0;
+ // virtual void visit(ExternalItem& item) = 0;
+ virtual void visit (ExternalStaticItem &item) = 0;
+ virtual void visit (ExternalFunctionItem &item) = 0;
+ virtual void visit (ExternBlock &block) = 0;
+
+ // rust-macro.h
+ virtual void visit (MacroMatchFragment &match) = 0;
+ virtual void visit (MacroMatchRepetition &match) = 0;
+ virtual void visit (MacroMatcher &matcher) = 0;
+ virtual void visit (MacroRulesDefinition &rules_def) = 0;
+ virtual void visit (MacroInvocation &macro_invoc) = 0;
+ virtual void visit (MetaItemPath &meta_item) = 0;
+ virtual void visit (MetaItemSeq &meta_item) = 0;
+ virtual void visit (MetaWord &meta_item) = 0;
+ virtual void visit (MetaNameValueStr &meta_item) = 0;
+ virtual void visit (MetaListPaths &meta_item) = 0;
+ virtual void visit (MetaListNameValueStr &meta_item) = 0;
+
+ // rust-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 &macro) {}
+
+ // 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 &param) {}
+ // 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 &macro_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 &param : 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 &macro) {}
+
+ // 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 &param) {}
+ // 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 &macro_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 &param : 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 &param : 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