From 29fb9e4d937f2d98734330f46f539514e2518cc3 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 10 Dec 2020 18:01:12 +0000 Subject: tweak to rust-system.h includes --- gcc/rust/rust-system.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'gcc') 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 #include #include +#include // Rust frontend requires C++11 minimum, so will have unordered_map and set #include @@ -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) -- cgit v1.1 From 3514168b990fd67225c59e84c7fffec075788905 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 10 Dec 2020 17:44:33 +0000 Subject: Introduce HIR Mapping This is the start of a bigger refactor of the compiler to follow the rustc internals. This introduces a mapping system for. - HirId which maps to any Hir Node within the current crate - LocalDefId any toplevel Hir Node HIR::Item within current crate - NodeId maps any AST node akin to HirId such that they can map back - DefId Cratea and localDefId combination --- gcc/rust/Make-lang.in | 3 +- gcc/rust/analysis/scope.h | 57 ------- gcc/rust/util/rust-hir-map.cc | 312 +++++++++++++++++++++++++++++++++++++ gcc/rust/util/rust-hir-map.h | 134 ++++++++++++++++ gcc/rust/util/rust-inference-var.h | 112 +++++++++++++ gcc/rust/util/scope.h | 78 ++++++++++ 6 files changed, 638 insertions(+), 58 deletions(-) delete mode 100644 gcc/rust/analysis/scope.h create mode 100644 gcc/rust/util/rust-hir-map.cc create mode 100644 gcc/rust/util/rust-hir-map.h create mode 100644 gcc/rust/util/rust-inference-var.h create mode 100644 gcc/rust/util/scope.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 234d51b..7159725 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -74,6 +74,7 @@ GRS_OBJS = \ rust/rust-scan.o \ rust/rust-compile.o \ rust/rust-macro-expand.o \ + rust/rust-hir-map.o \ $(END) # removed object files from here @@ -217,7 +218,7 @@ 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/util # add files that require cross-folder includes - currently rust-lang.o, rust-lex.o CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES) 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 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 Pop () - { - auto toplevel = scopeStack.back (); - scopeStack.pop_back (); - return toplevel; - } - - std ::map Peek () { return scopeStack.back (); } - -private: - std::vector > scopeStack; -}; - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc new file mode 100644 index 0000000..ff3e548 --- /dev/null +++ b/gcc/rust/util/rust-hir-map.cc @@ -0,0 +1,312 @@ +// 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 +// . + +#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 +{ + DefId val = 0; + val |= get_crate_num (); + val = val << sizeof (uint32_t); + val |= get_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 instance; + if (!instance) + instance = std::move (std::unique_ptr (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; + } + + 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; +} + +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; +} + +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_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 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; + } +} + +} // 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..cbe22a5 --- /dev/null +++ b/gcc/rust/util/rust-hir-map.h @@ -0,0 +1,134 @@ +// 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 +// . + +#ifndef RUST_HIR_MAP_H +#define RUST_HIR_MAP_H + +#include "rust-system.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 +typedef uint64_t DefId; + +#define DEF_ID_CRATE_MASK 0xFFFFFFFF00000000 +#define DEF_ID_LOCAL_DEF_MASK 0x00000000FFFFFFFF + +#define UNKNOWN_CREATENUM ((uint32_t) (-1)) +#define UNKNOWN_NODEID ((uint32_t) (-1)) +#define UNKNOWN_HIRID ((uint32_t) (-1)) +#define UNKNOWN_LOCAL_DEFID ((uint32_t) (-1)) +#define UNKNOWN_DEFID ((uint64_t) (-1)) + +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; + + 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 (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 walk_local_defids_for_crate (CrateNum crateNum, + std::function cb); + +private: + Mappings (); + + CrateNum crateNumItr; + CrateNum currentCrateNum; + + std::map hirIdIter; + std::map nodeIdIter; + std::map localIdIter; + + std::map astCrateMappings; + std::map hirCrateMappings; + + std::map defIdMappings; + std::map > localDefIdMappings; + std::map > hirItemMappings; + std::map > hirExprMappings; +}; + +} // namespace Analysis +} // namespace Rust + +#endif // RUST_HIR_MAP_H diff --git a/gcc/rust/util/rust-inference-var.h b/gcc/rust/util/rust-inference-var.h new file mode 100644 index 0000000..87decd5 --- /dev/null +++ b/gcc/rust/util/rust-inference-var.h @@ -0,0 +1,112 @@ +// 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 +// . + +#ifndef RUST_HIR_INFERENCE_VAR +#define RUST_HIR_INFERENCE_VAR + +#include "rust-system.h" +#include "rust-hir-full-decls.h" + +namespace Rust { +namespace HIR { + +class GeneralInferenceVariable; +class IntegralInferenceVariable; +class FloatInferenceVariable; +class InferenceVarVisitor +{ +public: + virtual void visit (GeneralInferenceVariable &v) {} + virtual void visit (IntegralInferenceVariable &v) {} + virtual void visit (FloatInferenceVariable &v) {} +}; + +// Base +class InferenceVariable +{ +public: + virtual ~InferenceVariable () {} + + virtual std::string as_string () const = 0; + + HIR::Type *get_type () { return resolved; } + + void set_type (HIR::Type *type) { resolved = type; } + + bool was_resolved () { return resolved != nullptr; } + + virtual void accept_vis (InferenceVarVisitor &vis) = 0; + +protected: + InferenceVariable () : resolved (nullptr) {} + + HIR::Type *resolved; +}; + +class GeneralInferenceVariable : public InferenceVariable +{ +public: + GeneralInferenceVariable () : InferenceVariable () {} + + void accept_vis (InferenceVarVisitor &vis) { vis.visit (*this); }; + + std::string as_string () const override + { + if (resolved) + return resolved->as_string (); + + return "[G::?T]"; + } +}; + +class IntegralInferenceVariable : public InferenceVariable +{ +public: + IntegralInferenceVariable () : InferenceVariable () {} + + void accept_vis (InferenceVarVisitor &vis) { vis.visit (*this); }; + + std::string as_string () const override + { + if (resolved) + return resolved->as_string (); + + return "[I::?T]"; + } +}; + +class FloatInferenceVariable : public InferenceVariable +{ +public: + FloatInferenceVariable () : InferenceVariable () {} + + void accept_vis (InferenceVarVisitor &vis) { vis.visit (*this); }; + + std::string as_string () const override + { + if (resolved) + return resolved->as_string (); + + return "[F::?T]"; + } +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_HIR_INFERENCE_VAR diff --git a/gcc/rust/util/scope.h b/gcc/rust/util/scope.h new file mode 100644 index 0000000..6e853c3 --- /dev/null +++ b/gcc/rust/util/scope.h @@ -0,0 +1,78 @@ +// 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 +// . + +#ifndef RUST_SCOPE_H +#define RUST_SCOPE_H + +#include "rust-system.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Analysis { + +template 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 Pop () + { + auto toplevel = scopeStack.back (); + scopeStack.pop_back (); + return toplevel; + } + + std ::map Peek () { return scopeStack.back (); } + +private: + std::vector > scopeStack; +}; + +} // namespace Analysis +} // namespace Rust + +#endif // RUST_SCOPE_H -- cgit v1.1 From 6c89617fc9525b726a494d4b44d19178049169a0 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 10 Dec 2020 17:48:11 +0000 Subject: Cleanup Makefile for Rust This adds some extra Flags to ignore unused warnings and no overloaded-virtuals. This helps with compilation error diagnosis. --- gcc/rust/Make-lang.in | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 7159725..182a086 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -218,7 +218,17 @@ 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 -I $(srcdir)/rust/util +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/hir_resolve \ + -I $(srcdir)/rust/util # add files that require cross-folder includes - currently rust-lang.o, rust-lex.o CFLAGS-rust/rust-lang.o += $(RUST_INCLUDES) @@ -227,33 +237,40 @@ 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) $< + $(COMPILE) $(RUST_CXXFLAGS) $(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) + -- cgit v1.1 From 97d2003e8c0027601648364c3561b6aa479c842e Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 10 Dec 2020 17:55:45 +0000 Subject: Add generated NodeId's to the AST NodeIds are going to be used for Hir->Ast lookups later on. --- gcc/rust/ast/rust-ast-full-decls.h | 528 +++++++++++++++++++------------------ gcc/rust/ast/rust-ast.h | 128 ++++++++- gcc/rust/ast/rust-expr.h | 41 ++- gcc/rust/ast/rust-item.h | 44 ++-- gcc/rust/ast/rust-path.h | 30 +++ 5 files changed, 481 insertions(+), 290 deletions(-) (limited to 'gcc') 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 +// . + #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 bdc1f12..fe60ae0 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 +// . + #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 -#include -#include +#include "rust-hir-map.h" // gccrs imports // required for AST::Token #include "rust-token.h" - #include "rust-location.h" namespace Rust { @@ -253,6 +266,95 @@ public: bool is_error () const { return value_as_string == ""; } }; +// A token tree with delimiters +class DelimTokenTree : public TokenTree, public AttrInput +{ + DelimType delim_type; + std::vector > 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 > token_trees + = std::vector > (), + 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 (ASTVisitor &vis) override; + + bool + check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override + { + // this should never be called - should be converted first + return false; + } + + AttrInput *parse_to_meta_item () const override; + + std::vector > to_token_stream () const override; + + std::unique_ptr clone_delim_token_tree () const + { + return std::unique_ptr (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 @@ -473,7 +575,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 +870,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 +955,13 @@ public: virtual void mark_for_strip () = 0; virtual bool is_marked_for_strip () const = 0; + NodeId get_node_id () const { return node_id; } + protected: // Constructor Expr (std::vector outer_attribs = std::vector ()) - : 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 +973,8 @@ protected: { outer_attrs = std::move (outer_attrs_to_set); } + + NodeId node_id; }; // AST node for an expression without an accompanying block - abstract diff --git a/gcc/rust/ast/rust-expr.h b/gcc/rust/ast/rust-expr.h index f86aa54..864ee1d 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 field_value, Location locus) + std::unique_ptr 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 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 field_value, Location locus) + std::unique_ptr 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 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,20 @@ public: void mark_for_strip () override { function = nullptr; } bool is_marked_for_strip () const override { return function == nullptr; } + void iterate_params (std::function 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); } + // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector > &get_params () const { @@ -2793,13 +2811,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 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 -. */ +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#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 param_type, std::vector 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 > trait_items, Visibility vis, std::vector outer_attrs, std::vector 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..20138b6 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 &get_segments () { return segments; } const std::vector &get_segments () const { return segments; } + + void iterate_path_segments (std::function 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 @@ -328,6 +339,7 @@ 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; } protected: /* Use covariance to implement clone function as returning this object rather @@ -404,6 +416,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 @@ -689,6 +708,17 @@ public: { return segments; } + + size_t get_num_segments () const { return segments.size (); } + + void iterate_segments (std::function cb) + { + for (auto it = segments.begin (); it != segments.end (); it++) + { + if (!cb ((*it).get ())) + return; + } + } }; struct QualifiedPathType -- cgit v1.1 From 5f2dd6de5bf2dc58a075aa0fe3c8ddf75eba8004 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 10 Dec 2020 17:56:09 +0000 Subject: Add in HIR Tree This is an IR based off the AST its almost a copy but with NodeMappings on the parent Tree Types. This should ideally have all macro tree's removed during the lowering process. --- gcc/rust/Make-lang.in | 6 + gcc/rust/hir/tree/rust-hir-cond-compilation.h | 248 + gcc/rust/hir/tree/rust-hir-expr.h | 4480 ++++++++++++++++++ gcc/rust/hir/tree/rust-hir-full-decls.h | 285 ++ gcc/rust/hir/tree/rust-hir-full-test.cc | 6100 +++++++++++++++++++++++++ gcc/rust/hir/tree/rust-hir-full.h | 32 + gcc/rust/hir/tree/rust-hir-item.h | 3293 +++++++++++++ gcc/rust/hir/tree/rust-hir-macro.h | 627 +++ gcc/rust/hir/tree/rust-hir-path.h | 850 ++++ gcc/rust/hir/tree/rust-hir-pattern.h | 1162 +++++ gcc/rust/hir/tree/rust-hir-stmt.h | 232 + gcc/rust/hir/tree/rust-hir-type.h | 864 ++++ gcc/rust/hir/tree/rust-hir-visitor.h | 244 + gcc/rust/hir/tree/rust-hir.h | 1459 ++++++ 14 files changed, 19882 insertions(+) create mode 100644 gcc/rust/hir/tree/rust-hir-cond-compilation.h create mode 100644 gcc/rust/hir/tree/rust-hir-expr.h create mode 100644 gcc/rust/hir/tree/rust-hir-full-decls.h create mode 100644 gcc/rust/hir/tree/rust-hir-full-test.cc create mode 100644 gcc/rust/hir/tree/rust-hir-full.h create mode 100644 gcc/rust/hir/tree/rust-hir-item.h create mode 100644 gcc/rust/hir/tree/rust-hir-macro.h create mode 100644 gcc/rust/hir/tree/rust-hir-path.h create mode 100644 gcc/rust/hir/tree/rust-hir-pattern.h create mode 100644 gcc/rust/hir/tree/rust-hir-stmt.h create mode 100644 gcc/rust/hir/tree/rust-hir-type.h create mode 100644 gcc/rust/hir/tree/rust-hir-visitor.h create mode 100644 gcc/rust/hir/tree/rust-hir.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 182a086..dd42b1d 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -75,6 +75,7 @@ GRS_OBJS = \ rust/rust-compile.o \ rust/rust-macro-expand.o \ rust/rust-hir-map.o \ + rust/rust-hir-full-test.o \ $(END) # removed object files from here @@ -274,3 +275,8 @@ rust/%.o: rust/util/%.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) + 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 +// . + +#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 clone_configuration_predicate () const + { + return std::unique_ptr ( + 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 > predicate_list; +}; + +// Predicate that returns true if all of the supplied predicates return true. +class ConfigurationAll : public ConfigurationPredicate +{ + std::vector > + predicate_list; // inlined form + +public: + ConfigurationAll ( + std::vector > 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 > + predicate_list; // inlined form + +public: + ConfigurationAny ( + std::vector > 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 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 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 cfg_attrs; +}; + +// TODO: relationship to other attributes? +class CfgAttrAttribute +{ + std::unique_ptr config_to_include; + std::vector cfg_attrs; + +public: + CfgAttrAttribute (ConfigurationPredicate *config_to_include, + std::vector 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..5f5bbf9 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -0,0 +1,4480 @@ +// 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 +// . + +#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 outer_attrs = std::vector ()) + : 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 clone_expr_with_block () const + { + return std::unique_ptr (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 outer_attrs = std::vector ()) + : 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 outer_attrs = std::vector ()) + : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), + literal (std::move (literal)), locus (locus) + {} + + // Unique pointer custom clone function + std::unique_ptr clone_literal_expr () const + { + return std::unique_ptr (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 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 main_or_left_expr; + + // Constructor (only for initialisation of expr purposes) + OperatorExpr (Analysis::NodeMapping mappings, + std::unique_ptr main_or_left_expr, + std::vector 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 borrow_lvalue, bool is_mut_borrow, + bool is_double_borrow, std::vector 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 deref_lvalue, + std::vector 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 potential_error_value, + std::vector 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 negated_value, NegationType negation_kind, + std::vector 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 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 left_value, + std::unique_ptr right_value, + ExprType expr_kind, Location locus) + : OperatorExpr (std::move (mappings), std::move (left_value), + std::vector (), 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 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 left_value, + std::unique_ptr right_value, ExprType comparison_kind, + Location locus) + : OperatorExpr (std::move (mappings), std::move (left_value), + std::vector (), 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 (); } + + /* 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 right_expr; + +public: + // Constructor calls OperatorExpr's protected constructor + LazyBooleanExpr (Analysis::NodeMapping mappings, + std::unique_ptr left_bool_expr, + std::unique_ptr right_bool_expr, ExprType expr_kind, + Location locus) + : OperatorExpr (std::move (mappings), std::move (left_bool_expr), + std::vector (), 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 (); } + +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 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_to_cast, + std::unique_ptr type_to_cast_to, Location locus) + : OperatorExpr (std::move (mappings), std::move (expr_to_cast), + std::vector (), 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 right_expr; + +public: + std::string as_string () const override; + + // Call OperatorExpr constructor to initialise left_expr + AssignmentExpr (Analysis::NodeMapping mappings, + std::unique_ptr value_to_assign_to, + std::unique_ptr value_to_assign, Location locus) + : OperatorExpr (std::move (mappings), std::move (value_to_assign_to), + std::vector (), 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 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 value_to_assign_to, + std::unique_ptr value_to_assign, + ExprType expr_kind, Location locus) + : OperatorExpr (std::move (mappings), std::move (value_to_assign_to), + std::vector (), 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 inner_attrs; + std::unique_ptr expr_in_parens; + + Location locus; + +public: + std::string as_string () const override; + + std::vector get_inner_attrs () const { return inner_attrs; } + + GroupedExpr (Analysis::NodeMapping mappings, + std::unique_ptr parenthesised_expr, + std::vector inner_attribs, + std::vector 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 clone_array_elems () const + { + return std::unique_ptr (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 > values; + + // TODO: should this store location data? + +public: + ArrayElemsValues (std::vector > 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 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 elem_to_copy; + std::unique_ptr num_copies; + + // TODO: should this store location data? + +public: + // Constructor requires pointers for polymorphism + ArrayElemsCopied (std::unique_ptr copied_elem, + std::unique_ptr 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 inner_attrs; + std::unique_ptr 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 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 array_elems, + std::vector inner_attribs, + std::vector 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 array_expr; + std::unique_ptr index_expr; + + Location locus; + +public: + std::string as_string () const override; + + ArrayIndexExpr (Analysis::NodeMapping mappings, + std::unique_ptr array_expr, + std::unique_ptr array_index_expr, + std::vector 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 inner_attrs; + + std::vector > tuple_elems; + // replaces (inlined version of) TupleElements + + Location locus; + +public: + std::string as_string () const override; + + std::vector get_inner_attrs () const { return inner_attrs; } + + TupleExpr (Analysis::NodeMapping mappings, + std::vector > tuple_elements, + std::vector inner_attribs, + std::vector 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 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 tuple_expr, TupleIndex index, + std::vector 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 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 inner_attrs; + + Location locus; + +public: + std::string as_string () const override; + + std::vector 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 inner_attribs, + std::vector 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 base_struct; + + // TODO: should this store location data? + StructBase (std::unique_ptr 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 clone_struct_expr_field () const + { + return std::unique_ptr (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 value; + +protected: + StructExprFieldWithVal (std::unique_ptr 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 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 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 fields; + std::vector > 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> 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 > expr_fields, Location locus, + StructBase base_struct = StructBase::error (), + std::vector inner_attribs = std::vector (), + std::vector outer_attribs = std::vector ()) + : 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 inner_attribs, + std::vector 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 inner_attrs; + std::vector > exprs; + + Location locus; + +public: + std::string as_string () const override; + + const std::vector &get_inner_attrs () const { return inner_attrs; } + + /*inline std::vector> get_exprs() const { + return exprs; + }*/ + + StructExprTuple (Analysis::NodeMapping mappings, PathInExpression struct_path, + std::vector > tuple_exprs, + std::vector inner_attribs, + std::vector 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 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 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 clone_enum_expr_field () const + { + return std::unique_ptr (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 value; + + // TODO: should this store location data? + +protected: + EnumExprFieldWithVal (std::unique_ptr 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 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 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 fields; + std::vector > fields; + + Location locus; + +public: + std::string as_string () const override; + + /*inline std::vector> get_fields() const + { return fields; + }*/ + + EnumExprStruct (Analysis::NodeMapping mappings, + PathInExpression enum_variant_path, + std::vector > variant_fields, + std::vector 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 > values; + + Location locus; + +public: + std::string as_string () const override; + + /*inline std::vector> get_values() const { + return values; + }*/ + + EnumExprTuple (Analysis::NodeMapping mappings, + PathInExpression enum_variant_path, + std::vector > variant_values, + std::vector 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 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 function; + // inlined form of CallParams + std::vector > params; + + Location locus; + +public: + std::string as_string () const override; + + CallExpr (Analysis::NodeMapping mappings, std::unique_ptr function_expr, + std::vector > function_params, + std::vector 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 (); } + + void iterate_params (std::function 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 receiver; + PathExprSegment method_name; + // inlined form of CallParams + std::vector > params; + + Location locus; + +public: + std::string as_string () const override; + + /*inline std::vector> get_params() const { + return params; + }*/ + + MethodCallExpr (Analysis::NodeMapping mappings, + std::unique_ptr call_receiver, + PathExprSegment method_path, + std::vector > method_params, + std::vector 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 receiver; + Identifier field; + + Location locus; + +public: + std::string as_string () const override; + + FieldAccessExpr (Analysis::NodeMapping mappings, + std::unique_ptr field_access_receiver, + Identifier field_name, std::vector 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; + + // bool has_type_given; + std::unique_ptr 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 param_pattern, + std::unique_ptr 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 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 closure_params, bool has_move, + std::vector 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 closure_inner; + +public: + std::string as_string () const override; + + // Constructor for a ClosureExprInner + ClosureExprInner (Analysis::NodeMapping mappings, + std::unique_ptr closure_inner_expr, + std::vector closure_params, Location locus, + bool is_move = false, + std::vector outer_attribs + = std::vector ()) + : 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 inner_attrs; + + // bool has_statements; + std::vector > statements; + // bool has_expr; + std::unique_ptr 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 > block_statements, + std::unique_ptr block_expr, + std::vector inner_attribs, + std::vector 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 clone_block_expr () const + { + return std::unique_ptr (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; + +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 return_type; + std::unique_ptr + 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 closure_return_type, + std::unique_ptr closure_expr, + std::vector closure_params, + Location locus, bool is_move = false, + std::vector outer_attribs + = std::vector ()) + : 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 outer_attribs + = std::vector ()) + : 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 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_in_break = nullptr, + std::vector outer_attribs = std::vector ()) + : 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 ()), + 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 from; + std::unique_ptr to; + +public: + std::string as_string () const override; + + RangeFromToExpr (Analysis::NodeMapping mappings, + std::unique_ptr range_from, + std::unique_ptr 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 from; + +public: + std::string as_string () const override; + + RangeFromExpr (Analysis::NodeMapping mappings, + std::unique_ptr 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 to; + +public: + std::string as_string () const override; + + // outer attributes not allowed + RangeToExpr (Analysis::NodeMapping mappings, std::unique_ptr 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 from; + std::unique_ptr to; + +public: + std::string as_string () const override; + + RangeFromToInclExpr (Analysis::NodeMapping mappings, + std::unique_ptr range_from, + std::unique_ptr 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 to; + +public: + std::string as_string () const override; + + RangeToInclExpr (Analysis::NodeMapping mappings, + std::unique_ptr 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 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 returned_expr = nullptr, + std::vector outer_attribs = std::vector ()) + : 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; + +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 expr; + + Location locus; + +public: + std::string as_string () const override; + + UnsafeBlockExpr (Analysis::NodeMapping mappings, + std::unique_ptr block_expr, + std::vector 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 loop_block; + +private: + Location locus; + +protected: + // Constructor for BaseLoopExpr + BaseLoopExpr (Analysis::NodeMapping mappings, + std::unique_ptr loop_block, Location locus, + LoopLabel loop_label = LoopLabel::error (), + std::vector outer_attribs + = std::vector ()) + : 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 loop_block, Location locus, + LoopLabel loop_label = LoopLabel::error (), + std::vector outer_attribs = std::vector ()) + : 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 condition; + +public: + std::string as_string () const override; + + // Constructor for while loop with loop label + WhileLoopExpr (Analysis::NodeMapping mappings, + std::unique_ptr loop_condition, + std::unique_ptr loop_block, Location locus, + LoopLabel loop_label = LoopLabel::error (), + std::vector outer_attribs + = std::vector ()) + : 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 > match_arm_patterns; // inlined + std::unique_ptr condition; + +public: + std::string as_string () const override; + + // Constructor with a loop label + WhileLetLoopExpr (Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr condition, + std::unique_ptr loop_block, Location locus, + LoopLabel loop_label = LoopLabel::error (), + std::vector outer_attribs + = std::vector ()) + : 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; + std::unique_ptr iterator_expr; + +public: + std::string as_string () const override; + + // Constructor with loop label + ForLoopExpr (Analysis::NodeMapping mappings, + std::unique_ptr loop_pattern, + std::unique_ptr iterator_expr, + std::unique_ptr loop_body, Location locus, + LoopLabel loop_label = LoopLabel::error (), + std::vector outer_attribs = std::vector ()) + : 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 condition; + std::unique_ptr if_block; + + Location locus; + +public: + std::string as_string () const override; + + IfExpr (Analysis::NodeMapping mappings, std::unique_ptr condition, + std::unique_ptr if_block, Location locus) + : ExprWithBlock (std::move (mappings), std::vector ()), + 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 clone_if_expr () const + { + return std::unique_ptr (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 else_block; + +public: + std::string as_string () const override; + + IfExprConseqElse (Analysis::NodeMapping mappings, + std::unique_ptr condition, + std::unique_ptr if_block, + std::unique_ptr 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 conseq_if_expr; + +public: + std::string as_string () const override; + + IfExprConseqIf (Analysis::NodeMapping mappings, + std::unique_ptr condition, + std::unique_ptr if_block, + std::unique_ptr 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 > match_arm_patterns; // inlined + std::unique_ptr value; + std::unique_ptr if_block; + + Location locus; + +public: + std::string as_string () const override; + + IfLetExpr (Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr value, std::unique_ptr if_block, + Location locus) + : ExprWithBlock (std::move (mappings), std::vector ()), + 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 clone_if_let_expr () const + { + return std::unique_ptr (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 if_let_expr; + +public: + std::string as_string () const override; + + IfExprConseqIfLet (Analysis::NodeMapping mappings, + std::unique_ptr condition, + std::unique_ptr if_block, + std::unique_ptr 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 else_block; + +public: + std::string as_string () const override; + + IfLetExprConseqElse ( + Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr value, std::unique_ptr if_block, + std::unique_ptr 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 if_expr; + +public: + std::string as_string () const override; + + IfLetExprConseqIf (Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr value, + std::unique_ptr if_block, + std::unique_ptr 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 if_let_expr; + +public: + std::string as_string () const override; + + IfLetExprConseqIfLet ( + Analysis::NodeMapping mappings, + std::vector > match_arm_patterns, + std::unique_ptr value, std::unique_ptr if_block, + std::unique_ptr 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 outer_attrs; + // MatchArmPatterns patterns; + std::vector > match_arm_patterns; // inlined + + // bool has_match_arm_guard; + // inlined from MatchArmGuard + std::unique_ptr 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 > match_arm_patterns, + std::unique_ptr guard_expr = nullptr, + std::vector outer_attrs = std::vector ()) + : 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::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 clone_match_case () const + { + return std::unique_ptr (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; + + /* 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) + : 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 block_expr; + + // TODO: should this store location data? + +public: + MatchCaseBlockExpr (MatchArm arm, std::unique_ptr 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; + + // TODO: should this store location data? + +public: + MatchCaseExpr (MatchArm arm, std::unique_ptr 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 branch_value; + std::vector inner_attrs; + + // bool has_match_arms; + // MatchArms match_arms; + // std::vector > match_arms; // inlined from + // MatchArms + std::vector 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 branch_value, + // std::vector > match_arms, + std::vector match_arms, + std::vector inner_attrs, + std::vector 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 awaited_expr; + + Location locus; + +public: + // TODO: ensure outer attributes are actually allowed + AwaitExpr (Analysis::NodeMapping mappings, std::unique_ptr awaited_expr, + std::vector 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 block_expr; + + Location locus; + +public: + AsyncBlockExpr (Analysis::NodeMapping mappings, + std::unique_ptr block_expr, bool has_move, + std::vector 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 +// . + +#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 +// . + +#include "rust-hir-full.h" +#include "rust-hir-visitor.h" +#include "rust-diagnostics.h" + +/* Compilation unit used for various HIR-related functions that would make + * the headers too long if they were defined inline and don't receive any + * benefits from being defined inline because they are virtual. Also used + * for various other stuff. */ + +namespace Rust { +namespace HIR { + +enum indent_mode +{ + enter, + out, + stay +}; + +std::string +indent_spaces (enum indent_mode mode) +{ + static int indent = 0; + std::string str = ""; + if (out == mode) + indent--; + for (int i = 0; i < indent; i++) + str += " "; + if (enter == mode) + indent++; + + return str; +} + +// Gets a string in a certain delim type. +std::string +get_string_in_delims (std::string str_input, DelimType delim_type) +{ + switch (delim_type) + { + case PARENS: + return "(" + str_input + ")"; + case SQUARE: + return "[" + str_input + "]"; + case CURLY: + return "{" + str_input + "}"; + default: + return "ERROR-MARK-STRING (delims)"; + } + gcc_unreachable (); +} + +// Converts a frag spec enum item to a string form. +std::string +frag_spec_to_str (MacroFragSpec frag_spec) +{ + switch (frag_spec) + { + case BLOCK: + return "block"; + case EXPR: + return "expr"; + case IDENT: + return "ident"; + case ITEM: + return "item"; + case LIFETIME: + return "lifetime"; + case LITERAL: + return "literal"; + case META: + return "meta"; + case PAT: + return "pat"; + case PATH: + return "path"; + case STMT: + return "stmt"; + case TT: + return "tt"; + case TY: + return "ty"; + case VIS: + return "vis"; + case INVALID: + return "INVALID_FRAG_SPEC"; + default: + return "ERROR_MARK_STRING - unknown frag spec"; + } +} + +std::string +Crate::as_string () const +{ + std::string str ("HIR::Crate: "); + // add utf8bom and shebang + if (has_utf8bom) + { + str += "\n has utf8bom"; + } + if (has_shebang) + { + str += "\n has shebang"; + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // items + str += "\n items: "; + if (items.empty ()) + { + str += "none"; + } + else + { + for (const auto &item : items) + { + // DEBUG: null pointer check + if (item == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - " + "null pointer item in crate."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + item->as_string (); + } + } + + return str + "\n::" + get_mappings ().as_string () + "\n"; +} + +std::string +Attribute::as_string () const +{ + std::string path_str = path.as_string (); + if (attr_input == nullptr) + { + return path_str; + } + else + { + return path_str + attr_input->as_string (); + } +} + +std::string +DelimTokenTree::as_string () const +{ + std::string start_delim; + std::string end_delim; + switch (delim_type) + { + case PARENS: + start_delim = "("; + end_delim = ")"; + break; + case SQUARE: + start_delim = "["; + end_delim = "]"; + break; + case CURLY: + start_delim = "{"; + end_delim = "}"; + break; + default: + fprintf (stderr, "Invalid delimiter type, " + "Should be PARENS, SQUARE, or CURLY."); + return "Invalid delimiter type"; + } + std::string str = start_delim; + if (!token_trees.empty ()) + { + for (const auto &tree : token_trees) + { + // DEBUG: null pointer check + if (tree == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "token tree in delim token tree."); + return "nullptr_POINTER_MARK"; + } + + str += tree->as_string (); + } + } + str += end_delim; + + return str; +} + +std::string +Token::as_string () const +{ + /* FIXME: only works when not identifier or literal or whatever, i.e. when + * doesn't store string value */ + // return get_token_description(token_id); + + // maybe fixed - stores everything as string though, so storage-inefficient + std::string quote = is_string_lit () ? "\"" : ""; + return quote + str + quote; +} + +std::string +SimplePathSegment::as_string () const +{ + return segment_name; +} + +std::string +SimplePath::as_string () const +{ + std::string path; + if (has_opening_scope_resolution) + { + path = "::"; + } + + // crappy hack because doing proper for loop would be more code + bool first_time = true; + for (const auto &segment : segments) + { + if (first_time) + { + path += segment.as_string (); + first_time = false; + } + else + { + path += "::" + segment.as_string (); + } + + // DEBUG: remove later. Checks for path error. + if (segment.is_error ()) + { + fprintf (stderr, + "segment in path is error - this should've been filtered " + "out. first segment " + "was '%s' \n", + segments.at (0).as_string ().c_str ()); + } + } + + return path; +} + +std::string +Visibility::as_string () const +{ + switch (public_vis_type) + { + case NONE: + return std::string ("pub"); + case CRATE: + return std::string ("ub(crate)"); + case SELF: + return std::string ("pub(self)"); + case SUPER: + return std::string ("pub(super)"); + case IN_PATH: + return std::string ("pub(in ") + in_path.as_string () + std::string (")"); + default: + gcc_unreachable (); + } +} + +// Creates a string that reflects the visibility stored. +std::string +VisItem::as_string () const +{ + // FIXME: can't do formatting on string to make identation occur. + std::string str = Item::as_string (); + + if (has_visibility ()) + { + str = visibility.as_string () + " "; + } + + return str; +} + +// Creates a string that reflects the outer attributes stored. +std::string +Item::as_string () const +{ + std::string str; + + if (!outer_attrs.empty ()) + { + for (const auto &attr : outer_attrs) + { + str += attr.as_string () + "\n"; + } + } + + return str; +} + +std::string +Module::as_string () const +{ + std::string vis_item = VisItem::as_string (); + + return vis_item + "mod " + module_name; +} + +std::string +ModuleBodied::as_string () const +{ + // get module string for "[vis] mod [name]" + std::string str = Module::as_string (); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // items + str += "\n items: "; + if (items.empty ()) + { + str += "none"; + } + else + { + for (const auto &item : items) + { + // DEBUG: null pointer check + if (item == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - " + "null pointer item in crate."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + item->as_string (); + } + } + + return str + "\n"; +} + +std::string +ModuleNoBody::as_string () const +{ + std::string str = Module::as_string (); + + str += "\n no body (reference to external file)"; + + return str + "\n"; +} + +std::string +StaticItem::as_string () const +{ + std::string str = VisItem::as_string (); + + str += indent_spaces (stay) + "static"; + + if (has_mut) + { + str += " mut"; + } + + str += name; + + // DEBUG: null pointer check + if (type == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - null " + "pointer type in static item."); + return "nullptr_POINTER_MARK"; + } + str += "\n" + indent_spaces (stay) + "Type: " + type->as_string (); + + // DEBUG: null pointer check + if (expr == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - null " + "pointer expr in static item."); + return "nullptr_POINTER_MARK"; + } + str += "\n" + indent_spaces (stay) + "Expression: " + expr->as_string (); + + return str + "\n"; +} + +std::string +ExternCrate::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "extern crate " + referenced_crate; + + if (has_as_clause ()) + { + str += " as " + as_clause_name; + } + + return str; +} + +std::string +TupleStruct::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "struct " + struct_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in enum."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + // tuple fields + str += "\n Tuple fields: "; + if (fields.empty ()) + { + str += "none"; + } + else + { + for (const auto &field : fields) + { + str += "\n " + field.as_string (); + } + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +ConstantItem::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "const " + identifier; + + // DEBUG: null pointer check + if (type == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - null " + "pointer type in const item."); + return "nullptr_POINTER_MARK"; + } + str += "\n Type: " + type->as_string (); + + // DEBUG: null pointer check + if (const_expr == nullptr) + { + fprintf (stderr, "something really terrible has gone wrong - null " + "pointer expr in const item."); + return "nullptr_POINTER_MARK"; + } + str += "\n Expression: " + const_expr->as_string (); + + return str + "\n"; +} + +std::string +InherentImpl::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "impl "; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in inherent impl."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Type: " + trait_type->as_string (); + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // inherent impl items + str += "\n Inherent impl items: "; + if (!has_impl_items ()) + { + str += "none"; + } + else + { + for (const auto &item : impl_items) + { + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +Method::as_string () const +{ + std::string str ("Method: \n "); + + str += vis.as_string () + " " + qualifiers.as_string (); + + str += " fn " + method_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in method."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Self param: " + self_param.as_string (); + + str += "\n Function params: "; + if (function_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : function_params) + { + str += "\n " + param.as_string (); + } + } + + str += "\n Return type: "; + if (has_return_type ()) + { + str += return_type->as_string (); + } + else + { + str += "none (void)"; + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + str += "\n Block expr (body): \n "; + str += expr->as_string (); + + return str; +} + +std::string +StructStruct::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "struct " + struct_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in enum."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + // struct fields + str += "\n Struct fields: "; + if (is_unit) + { + str += "none (unit)"; + } + else if (fields.empty ()) + { + str += "none (non-unit)"; + } + else + { + for (const auto &field : fields) + { + str += "\n " + field.as_string (); + } + } + + return str; +} + +std::string +UseDeclaration::as_string () const +{ + std::string str = VisItem::as_string (); + + // DEBUG: null pointer check + if (use_tree == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer use tree in " + "use declaration."); + return "nullptr_POINTER_MARK"; + } + + str += "use " + use_tree->as_string (); + + return str; +} + +std::string +UseTreeGlob::as_string () const +{ + switch (glob_type) + { + case NO_PATH: + return "*"; + case GLOBAL: + return "::*"; + case PATH_PREFIXED: { + std::string path_str = path.as_string (); + return path_str + "::*"; + } + default: + // some kind of error + return "ERROR-PATH"; + } + gcc_unreachable (); +} + +std::string +UseTreeList::as_string () const +{ + std::string path_str; + switch (path_type) + { + case NO_PATH: + path_str = "{"; + break; + case GLOBAL: + path_str = "::{"; + break; + case PATH_PREFIXED: { + path_str = path.as_string () + "::{"; + break; + } + default: + // some kind of error + return "ERROR-PATH-LIST"; + } + + if (has_trees ()) + { + auto i = trees.begin (); + auto e = trees.end (); + + // DEBUG: null pointer check + if (*i == nullptr) + { + fprintf (stderr, + "something really terrible has gone wrong - null pointer " + "tree in use tree list."); + return "nullptr_POINTER_MARK"; + } + + for (; i != e; i++) + { + path_str += (*i)->as_string (); + if (e != i + 1) + path_str += ", "; + } + } + else + { + path_str += "none"; + } + + return path_str + "}"; +} + +std::string +UseTreeRebind::as_string () const +{ + std::string path_str = path.as_string (); + + switch (bind_type) + { + case NONE: + // nothing to add, just path + break; + case IDENTIFIER: + path_str += " as " + identifier; + break; + case WILDCARD: + path_str += " as _"; + break; + default: + // error + return "ERROR-PATH-REBIND"; + } + + return path_str; +} + +std::string +Enum::as_string () const +{ + std::string str = VisItem::as_string (); + str += enum_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in enum."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + // items + str += "\n Items: "; + if (items.empty ()) + { + str += "none"; + } + else + { + for (const auto &item : items) + { + // DEBUG: null pointer check + if (item == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "enum item in enum."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +Trait::as_string () const +{ + std::string str = VisItem::as_string (); + + if (has_unsafe) + { + str += "unsafe "; + } + + str += "trait " + name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in trait."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Type param bounds: "; + if (!has_type_param_bounds ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + // DEBUG: null pointer check + if (bound == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "type param bound in trait."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + bound->as_string (); + } + } + + str += "\n Where clause: "; + if (!has_where_clause ()) + { + str += "none"; + } + else + { + str += where_clause.as_string (); + } + + str += "\n Trait items: "; + if (!has_trait_items ()) + { + str += "none"; + } + else + { + for (const auto &item : trait_items) + { + // DEBUG: null pointer check + if (item == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "trait item in trait."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +Union::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "union " + union_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in union."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + // struct fields + str += "\n Struct fields (variants): "; + if (variants.empty ()) + { + str += "none"; + } + else + { + for (const auto &field : variants) + { + str += "\n " + field.as_string (); + } + } + + return str; +} + +std::string +Function::as_string () const +{ + std::string str = VisItem::as_string () + "\n"; + std::string qstr = qualifiers.as_string (); + if ("" != qstr) + str += qstr + " "; + + if (has_function_return_type ()) + { + // DEBUG: null pointer check + if (return_type == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer return " + "type in function."); + return "nullptr_POINTER_MARK"; + } + + str += return_type->as_string () + " "; + } + else + { + str += "void "; + } + + str += function_name; + + if (has_generics ()) + { + str += "<"; + + auto i = generic_params.begin (); + auto e = generic_params.end (); + + // DEBUG: null pointer check + if (i == e) + { + fprintf (stderr, + "something really terrible has gone wrong - null pointer " + "generic param in function item."); + return "nullptr_POINTER_MARK"; + } + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + str += ">"; + } + + if (has_function_params ()) + { + auto i = function_params.begin (); + auto e = function_params.end (); + str += "("; + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + str += ")"; + } + else + { + str += "()"; + } + + if (has_where_clause ()) + { + str += " where " + where_clause.as_string (); + } + + str += "\n"; + + // DEBUG: null pointer check + if (function_body == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer function " + "body in function."); + return "nullptr_POINTER_MARK"; + } + return str + function_body->as_string () + "::" + get_mappings ().as_string () + + "\n"; +} + +std::string +WhereClause::as_string () const +{ + // just print where clause items, don't mention "where" or "where clause" + std::string str; + + if (where_clause_items.empty ()) + { + str = "none"; + } + else + { + for (const auto &item : where_clause_items) + { + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +BlockExpr::as_string () const +{ + std::string istr = indent_spaces (enter); + std::string str = istr + "BlockExpr:\n" + istr; + // get outer attributes + str += "{\n" + indent_spaces (stay) + Expr::as_string (); + + // inner attributes + str += "\n" + indent_spaces (stay) + "inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n" + indent_spaces (stay) + attr.as_string (); + } + } + + // statements + str += "\n" + indent_spaces (stay) + "statements: "; + if (statements.empty ()) + { + str += "none"; + } + else + { + for (const auto &stmt : statements) + { + // DEBUG: null pointer check + if (stmt == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "stmt in block expr."); + return "nullptr_POINTER_MARK"; + } + + str += "\n" + indent_spaces (stay) + stmt->as_string (); + } + } + + // final expression + str += "\n" + indent_spaces (stay) + "final expression: "; + if (expr == nullptr) + { + str += "none"; + } + else + { + str += "\n" + expr->as_string (); + } + + str += "\n" + indent_spaces (out) + "}"; + return str; +} + +std::string +TraitImpl::as_string () const +{ + std::string str = VisItem::as_string (); + + if (has_unsafe) + { + str += "unsafe "; + } + + str += "impl "; + + // generic params + str += "\n Generic params: "; + if (!has_generics ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + str += "\n " + param->as_string (); + } + } + + str += "\n Has exclam: "; + if (has_exclam) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n TypePath (to trait): " + trait_path.as_string (); + + str += "\n Type (struct to impl on): " + trait_type->as_string (); + + str += "\n Where clause: "; + if (!has_where_clause ()) + { + str += "none"; + } + else + { + str += where_clause.as_string (); + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n trait impl items: "; + if (!has_impl_items ()) + { + str += "none"; + } + else + { + for (const auto &item : impl_items) + { + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +TypeAlias::as_string () const +{ + std::string str = VisItem::as_string (); + + str += " " + new_type_name; + + // generic params + str += "\n Generic params: "; + if (!has_generics ()) + { + str += "none"; + } + else + { + auto i = generic_params.begin (); + auto e = generic_params.end (); + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + } + + str += "\n Where clause: "; + if (!has_where_clause ()) + { + str += "none"; + } + else + { + str += where_clause.as_string (); + } + + str += "\n Type: " + existing_type->as_string (); + + return str; +} + +std::string +MacroInvocationSemi::as_string () const +{ + // get outer attrs + std::string str = MacroItem::as_string (); + + str += "\n" + path.as_string () + "!"; + + std::string tok_trees; + if (token_trees.empty ()) + { + tok_trees = "none"; + } + else + { + auto i = token_trees.begin (); + auto e = token_trees.end (); + + // DEBUG: null pointer check + if (i == e) + { + fprintf (stderr, + "something really terrible has gone wrong - null pointer " + "token tree in macro invocation semi."); + return "nullptr_POINTER_MARK"; + } + + std::string s; + for (; i != e; i++) + { + s += (*i)->as_string (); + if (e != i + 1) + s += ", "; + } + + tok_trees += get_string_in_delims (s, delim_type); + } + + return str; +} + +std::string +ExternBlock::as_string () const +{ + std::string str = VisItem::as_string (); + + str += "extern "; + if (has_abi ()) + { + str += "\"" + abi + "\" "; + } + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n external items: "; + if (!has_extern_items ()) + { + str += "none"; + } + else + { + for (const auto &item : extern_items) + { + str += "\n " + item->as_string (); + } + } + + return str; +} + +std::string +MacroRule::as_string () const +{ + std::string str ("Macro rule: "); + + str += "\n Matcher: \n "; + str += matcher.as_string (); + + str += "\n Transcriber: \n "; + str += transcriber.as_string (); + + return str; +} + +std::string +MacroRulesDefinition::as_string () const +{ + std::string str ("macro_rules!"); + + str += rule_name; + + str += "\n Macro rules: "; + if (rules.empty ()) + { + str += "none"; + } + else + { + for (const auto &rule : rules) + { + str += "\n " + rule.as_string (); + } + } + + str += "\n Delim type: "; + switch (delim_type) + { + case PARENS: + str += "parentheses"; + break; + case SQUARE: + str += "square"; + break; + case CURLY: + str += "curly"; + break; + default: + return "ERROR_MARK_STRING - delim type in macro invocation"; + } + + return str; +} + +std::string +MacroInvocation::as_string () const +{ + return "MacroInvocation: " + path.as_string () + "!" + + token_tree.as_string (); +} + +std::string +PathInExpression::as_string () const +{ + std::string str; + + if (has_opening_scope_resolution) + { + str = "::"; + } + + return str + PathPattern::as_string () + "::" + get_mappings ().as_string (); +} + +std::string +ExprStmtWithBlock::as_string () const +{ + std::string str = indent_spaces (enter) + "ExprStmtWithBlock: \n"; + + if (expr == nullptr) + { + str += "none (this should not happen and is an error)"; + } + else + { + indent_spaces (enter); + str += expr->as_string (); + indent_spaces (out); + } + + indent_spaces (out); + return str; +} + +std::string +ClosureParam::as_string () const +{ + std::string str (pattern->as_string ()); + + if (has_type_given ()) + { + str += " : " + type->as_string (); + } + + return str; +} + +std::string +ClosureExpr::as_string () const +{ + std::string str ("ClosureExpr:\n Has move: "); + if (has_move) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n Params: "; + if (params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : params) + { + str += "\n " + param.as_string (); + } + } + + return str; +} + +std::string +ClosureExprInnerTyped::as_string () const +{ + std::string str = ClosureExpr::as_string (); + + str += "\n Return type: " + return_type->as_string (); + + str += "\n Body: " + expr->as_string (); + + return str; +} + +std::string +PathPattern::as_string () const +{ + std::string str; + + for (const auto &segment : segments) + { + str += segment.as_string () + "::"; + } + + // basically a hack - remove last two characters of string (remove final ::) + str.erase (str.length () - 2); + + return str; +} + +std::string +QualifiedPathType::as_string () const +{ + std::string str ("<"); + str += type_to_invoke_on->as_string (); + + if (has_as_clause ()) + { + str += " as " + trait_path.as_string (); + } + + return str + ">"; +} + +std::string +QualifiedPathInExpression::as_string () const +{ + return path_type.as_string () + "::" + PathPattern::as_string (); +} + +std::string +BorrowExpr::as_string () const +{ + std::string str ("&"); + + if (double_borrow) + { + str += "&"; + } + + if (is_mut) + { + str += "mut "; + } + + str += main_or_left_expr->as_string (); + + return str; +} + +std::string +ReturnExpr::as_string () const +{ + std::string str ("return "); + + if (has_return_expr ()) + { + str += return_expr->as_string (); + } + + return str + "::" + get_mappings ().as_string (); +} + +std::string +GroupedExpr::as_string () const +{ + std::string str ("Grouped expr:"); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n Expr in parens: " + expr_in_parens->as_string (); + + return str; +} + +std::string +RangeToExpr::as_string () const +{ + return ".." + to->as_string (); +} + +std::string +ContinueExpr::as_string () const +{ + std::string str ("continue "); + + if (has_label ()) + { + str += label.as_string (); + } + + return str; +} + +std::string +NegationExpr::as_string () const +{ + std::string str; + + switch (negation_type) + { + case NEGATE: + str = "-"; + break; + case NOT: + str = "!"; + break; + default: + return "ERROR_MARK_STRING - negation expr"; + } + + str += main_or_left_expr->as_string (); + + return str; +} + +std::string +RangeFromExpr::as_string () const +{ + return from->as_string () + ".."; +} + +std::string +RangeFullExpr::as_string () const +{ + return ".."; +} + +std::string +ArrayIndexExpr::as_string () const +{ + return array_expr->as_string () + "[" + index_expr->as_string () + "]"; +} + +std::string +AssignmentExpr::as_string () const +{ + return main_or_left_expr->as_string () + " = " + right_expr->as_string () + + "::" + get_mappings ().as_string (); +} + +std::string +AsyncBlockExpr::as_string () const +{ + std::string str = "AsyncBlockExpr: "; + + // get outer attributes + str += "\n " + Expr::as_string (); + + str += "\n Has move: "; + str += has_move ? "true" : "false"; + + return str + "\n" + block_expr->as_string (); +} + +std::string +ComparisonExpr::as_string () const +{ + std::string str (main_or_left_expr->as_string ()); + + switch (expr_type) + { + case EQUAL: + str += " == "; + break; + case NOT_EQUAL: + str += " != "; + break; + case GREATER_THAN: + str += " > "; + break; + case LESS_THAN: + str += " < "; + break; + case GREATER_OR_EQUAL: + str += " >= "; + break; + case LESS_OR_EQUAL: + str += " <= "; + break; + default: + return "ERROR_MARK_STRING - comparison expr"; + } + + str += right_expr->as_string (); + + return str; +} + +std::string +MethodCallExpr::as_string () const +{ + std::string str ("MethodCallExpr: \n Object (receiver) expr: "); + + str += receiver->as_string (); + + str += "\n Method path segment: \n"; + + str += method_name.as_string (); + + str += "\n Call params:"; + if (params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : params) + { + if (param == nullptr) + { + return "ERROR_MARK_STRING - method call expr param is null"; + } + + str += "\n " + param->as_string (); + } + } + + return str; +} + +std::string +TupleIndexExpr::as_string () const +{ + return tuple_expr->as_string () + "." + std::to_string (tuple_index); +} + +std::string +DereferenceExpr::as_string () const +{ + return "*" + main_or_left_expr->as_string (); +} + +std::string +FieldAccessExpr::as_string () const +{ + return receiver->as_string () + "." + field; +} + +std::string +LazyBooleanExpr::as_string () const +{ + std::string str (main_or_left_expr->as_string ()); + + switch (expr_type) + { + case LOGICAL_OR: + str += " || "; + break; + case LOGICAL_AND: + str += " && "; + break; + default: + return "ERROR_MARK_STRING - lazy boolean expr out of bounds"; + } + + str += right_expr->as_string (); + + return str; +} + +std::string +RangeFromToExpr::as_string () const +{ + return from->as_string () + ".." + to->as_string (); +} + +std::string +RangeToInclExpr::as_string () const +{ + return "..=" + to->as_string (); +} + +std::string +UnsafeBlockExpr::as_string () const +{ + std::string istr = indent_spaces (enter); + std::string str = istr + "UnsafeBlockExpr:"; + str += istr + "{"; + + // get outer attributes + str += "\n" + indent_spaces (stay) + Expr::as_string (); + + return str + "\n" + indent_spaces (out) + "}\n" + expr->as_string (); +} + +std::string +ClosureExprInner::as_string () const +{ + std::string str = ClosureExpr::as_string (); + + str += "\n Expression: " + closure_inner->as_string (); + + return str; +} + +std::string +IfExpr::as_string () const +{ + std::string str ("IfExpr: "); + + str += "\n Condition expr: " + condition->as_string (); + + str += "\n If block expr: " + if_block->as_string (); + + return str; +} + +std::string +IfExprConseqElse::as_string () const +{ + std::string str = IfExpr::as_string (); + + str += "\n Else block expr: " + else_block->as_string (); + + return str; +} + +std::string +IfExprConseqIf::as_string () const +{ + std::string str = IfExpr::as_string (); + + str += "\n Else if expr: \n " + conseq_if_expr->as_string (); + + return str; +} + +std::string +IfExprConseqIfLet::as_string () const +{ + std::string str = IfExpr::as_string (); + + str += "\n Else if let expr: \n " + if_let_expr->as_string (); + + return str; +} + +std::string +IfLetExpr::as_string () const +{ + std::string str ("IfLetExpr: "); + + str += "\n Condition match arm patterns: "; + if (match_arm_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &pattern : match_arm_patterns) + { + str += "\n " + pattern->as_string (); + } + } + + str += "\n Scrutinee expr: " + value->as_string (); + + str += "\n If let block expr: " + if_block->as_string (); + + return str; +} + +std::string +IfLetExprConseqElse::as_string () const +{ + std::string str = IfLetExpr::as_string (); + + str += "\n Else block expr: " + else_block->as_string (); + + return str; +} + +std::string +IfLetExprConseqIf::as_string () const +{ + std::string str = IfLetExpr::as_string (); + + str += "\n Else if expr: \n " + if_expr->as_string (); + + return str; +} + +std::string +IfLetExprConseqIfLet::as_string () const +{ + std::string str = IfLetExpr::as_string (); + + str += "\n Else if let expr: \n " + if_let_expr->as_string (); + + return str; +} + +std::string +RangeFromToInclExpr::as_string () const +{ + return from->as_string () + "..=" + to->as_string (); +} + +std::string +ErrorPropagationExpr::as_string () const +{ + return main_or_left_expr->as_string () + "?"; +} + +std::string +CompoundAssignmentExpr::as_string () const +{ + std::string operator_str; + operator_str.reserve (1); + + // get operator string + switch (expr_type) + { + case ADD: + operator_str = "+"; + break; + case SUBTRACT: + operator_str = "-"; + break; + case MULTIPLY: + operator_str = "*"; + break; + case DIVIDE: + operator_str = "/"; + break; + case MODULUS: + operator_str = "%"; + break; + case BITWISE_AND: + operator_str = "&"; + break; + case BITWISE_OR: + operator_str = "|"; + break; + case BITWISE_XOR: + operator_str = "^"; + break; + case LEFT_SHIFT: + operator_str = "<<"; + break; + case RIGHT_SHIFT: + operator_str = ">>"; + break; + default: + operator_str = "invalid operator. wtf"; + break; + } + + operator_str += "="; + + std::string str ("CompoundAssignmentExpr: "); + if (main_or_left_expr == nullptr || right_expr == nullptr) + { + str += "error. this is probably a parsing failure."; + } + else + { + str += "\n left: " + main_or_left_expr->as_string (); + str += "\n right: " + right_expr->as_string (); + str += "\n operator: " + operator_str; + } + + return str; +} + +std::string +ArithmeticOrLogicalExpr::as_string () const +{ + std::string operator_str; + operator_str.reserve (1); + + // get operator string + switch (expr_type) + { + case ADD: + operator_str = "+"; + break; + case SUBTRACT: + operator_str = "-"; + break; + case MULTIPLY: + operator_str = "*"; + break; + case DIVIDE: + operator_str = "/"; + break; + case MODULUS: + operator_str = "%"; + break; + case BITWISE_AND: + operator_str = "&"; + break; + case BITWISE_OR: + operator_str = "|"; + break; + case BITWISE_XOR: + operator_str = "^"; + break; + case LEFT_SHIFT: + operator_str = "<<"; + break; + case RIGHT_SHIFT: + operator_str = ">>"; + break; + default: + operator_str = "invalid operator. wtf"; + break; + } + + std::string str ("ArithmeticOrLogicalExpr: "); + if (main_or_left_expr == nullptr || right_expr == nullptr) + { + str += "error. this is probably a parsing failure."; + } + else + { + str += main_or_left_expr->as_string () + " "; + str += operator_str + " "; + str += right_expr->as_string (); + } + + return str + "::" + get_mappings ().as_string (); +} + +std::string +CallExpr::as_string () const +{ + std::string str = function->as_string () + "("; + if (!has_params ()) + str += "none"; + else + { + for (const auto ¶m : params) + { + if (param == nullptr) + { + return "ERROR_MARK_STRING - call expr param is null"; + } + + str += param->as_string () + ","; + } + } + return str + ")" + "::" + get_mappings ().as_string (); +} + +std::string +WhileLoopExpr::as_string () const +{ + std::string str ("WhileLoopExpr: "); + + str += "\n Label: "; + if (!has_loop_label ()) + { + str += "none"; + } + else + { + str += loop_label.as_string (); + } + + str += "\n Conditional expr: " + condition->as_string (); + + str += "\n Loop block: " + loop_block->as_string (); + + return str; +} + +std::string +WhileLetLoopExpr::as_string () const +{ + std::string str ("WhileLetLoopExpr: "); + + str += "\n Label: "; + if (!has_loop_label ()) + { + str += "none"; + } + else + { + str += loop_label.as_string (); + } + + str += "\n Match arm patterns: "; + if (match_arm_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &pattern : match_arm_patterns) + { + str += "\n " + pattern->as_string (); + } + } + + str += "\n Scrutinee expr: " + condition->as_string (); + + str += "\n Loop block: " + loop_block->as_string (); + + return str; +} + +std::string +LoopExpr::as_string () const +{ + std::string str ("LoopExpr: (infinite loop)"); + + str += "\n Label: "; + if (!has_loop_label ()) + { + str += "none"; + } + else + { + str += loop_label.as_string (); + } + + str += "\n Loop block: " + loop_block->as_string (); + + return str; +} + +std::string +ArrayExpr::as_string () const +{ + std::string str ("ArrayExpr:"); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n Array elems: "; + if (!has_array_elems ()) + { + str += "none"; + } + else + { + str += internal_elements->as_string (); + } + + return str; +} + +std::string +AwaitExpr::as_string () const +{ + return awaited_expr->as_string () + ".await"; +} + +std::string +BreakExpr::as_string () const +{ + std::string str ("break "); + + if (has_label ()) + { + str += label.as_string () + " "; + } + + if (has_break_expr ()) + { + str += break_expr->as_string (); + } + + return str; +} + +std::string +LoopLabel::as_string () const +{ + return label.as_string () + ": (label) "; +} + +std::string +MatchArm::as_string () const +{ + // outer attributes + std::string str = "Outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\nPatterns: "; + if (match_arm_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &pattern : match_arm_patterns) + { + str += "\n " + pattern->as_string (); + } + } + + str += "\nGuard expr: "; + if (!has_match_arm_guard ()) + { + str += "none"; + } + else + { + str += guard_expr->as_string (); + } + + return str; +} + +std::string +MatchCase::as_string () const +{ + std::string str ("MatchCase: (match arm) "); + + str += "\n Match arm matcher: \n" + arm.as_string (); + str += "\n Expr: " + expr->as_string (); + + return str; +} + +/*std::string +MatchCaseBlockExpr::as_string () const +{ + std::string str = MatchCase::as_string (); + + str += "\n Block expr: " + block_expr->as_string (); + + return str; +} + +std::string +MatchCaseExpr::as_string () const +{ + std::string str = MatchCase::as_string (); + + str += "\n Expr: " + expr->as_string (); + + return str; +}*/ + +std::string +MatchExpr::as_string () const +{ + std::string str ("MatchExpr:"); + + str += "\n Scrutinee expr: " + branch_value->as_string (); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // match arms + str += "\n Match arms: "; + if (match_arms.empty ()) + { + str += "none"; + } + else + { + for (const auto &arm : match_arms) + str += "\n " + arm.as_string (); + } + + return str; +} + +std::string +TupleExpr::as_string () const +{ + std::string str ("TupleExpr:"); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n Tuple elements: "; + if (tuple_elems.empty ()) + { + str += "none"; + } + else + { + for (const auto &elem : tuple_elems) + { + str += "\n " + elem->as_string (); + } + } + + return str; +} + +std::string +ExprStmtWithoutBlock::as_string () const +{ + std::string str ("ExprStmtWithoutBlock:\n"); + indent_spaces (enter); + str += indent_spaces (stay); + + if (expr == nullptr) + { + str += "none (this shouldn't happen and is probably an error)"; + } + else + { + str += expr->as_string (); + } + indent_spaces (out); + + return str; +} + +std::string +FunctionParam::as_string () const +{ + return param_name->as_string () + " : " + type->as_string (); +} + +std::string +FunctionQualifiers::as_string () const +{ + std::string str; + + switch (const_status) + { + case NONE: + // do nothing + break; + case CONST: + str += "const "; + break; + case ASYNC: + str += "async "; + break; + default: + return "ERROR_MARK_STRING: async-const status failure"; + } + + if (has_unsafe) + { + str += "unsafe "; + } + + if (has_extern) + { + str += "extern"; + if (extern_abi != "") + { + str += " \"" + extern_abi + "\""; + } + } + + return str; +} + +std::string +TraitBound::as_string () const +{ + std::string str ("TraitBound:"); + + str += "\n Has opening question mark: "; + if (opening_question_mark) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n For lifetimes: "; + if (!has_for_lifetimes ()) + { + str += "none"; + } + else + { + for (const auto &lifetime : for_lifetimes) + { + str += "\n " + lifetime.as_string (); + } + } + + str += "\n Type path: " + type_path.as_string (); + + return str; +} + +std::string +MacroMatcher::as_string () const +{ + std::string str ("Macro matcher: "); + + str += "\n Delim type: "; + + switch (delim_type) + { + case PARENS: + str += "parentheses"; + break; + case SQUARE: + str += "square"; + break; + case CURLY: + str += "curly"; + break; + default: + return "ERROR_MARK_STRING - macro matcher delim"; + } + + str += "\n Matches: "; + + if (matches.empty ()) + { + str += "none"; + } + else + { + for (const auto &match : matches) + { + str += "\n " + match->as_string (); + } + } + + return str; +} + +std::string +LifetimeParam::as_string () const +{ + std::string str ("LifetimeParam: "); + + str += "\n Outer attribute: "; + if (!has_outer_attribute ()) + { + str += "none"; + } + else + { + str += outer_attr.as_string (); + } + + str += "\n Lifetime: " + lifetime.as_string (); + + str += "\n Lifetime bounds: "; + if (!has_lifetime_bounds ()) + { + str += "none"; + } + else + { + for (const auto &bound : lifetime_bounds) + { + str += "\n " + bound.as_string (); + } + } + + return str; +} + +std::string +MacroMatchFragment::as_string () const +{ + return "$" + ident + ": " + frag_spec_to_str (frag_spec); +} + +std::string +QualifiedPathInType::as_string () const +{ + std::string str = path_type.as_string (); + + for (const auto &segment : segments) + { + str += "::" + segment->as_string (); + } + + return str; +} + +std::string +MacroMatchRepetition::as_string () const +{ + std::string str ("Macro match repetition: "); + + str += "\n Matches: "; + if (matches.empty ()) + { + str += "none"; + } + else + { + for (const auto &match : matches) + { + str += "\n " + match->as_string (); + } + } + + str += "\n Sep: "; + if (!has_sep ()) + { + str += "none"; + } + else + { + str += sep->as_string (); + } + + str += "\n Op: "; + switch (op) + { + case ASTERISK: + str += "*"; + break; + case PLUS: + str += "+"; + break; + case QUESTION_MARK: + str += "?"; + break; + case NONE: + str += "no op? shouldn't be allowed"; + break; + default: + return "ERROR_MARK_STRING - unknown op in macro match repetition"; + } + + return str; +} + +std::string +Lifetime::as_string () const +{ + if (is_error ()) + { + return "error lifetime"; + } + + switch (lifetime_type) + { + case NAMED: + return "'" + lifetime_name; + case STATIC: + return "'static"; + case WILDCARD: + return "'_"; + default: + return "ERROR-MARK-STRING: lifetime type failure"; + } +} + +std::string +TypePath::as_string () const +{ + std::string str; + + if (has_opening_scope_resolution) + { + str = "::"; + } + + for (const auto &segment : segments) + { + str += segment->as_string () + "::"; + } + + // kinda hack - remove last 2 '::' characters + str.erase (str.length () - 2); + + return str; +} + +std::string +TypeParam::as_string () const +{ + std::string str ("TypeParam: "); + + str += "\n Outer attribute: "; + if (!has_outer_attribute ()) + { + str += "none"; + } + else + { + str += outer_attr.as_string (); + } + + str += "\n Identifier: " + type_representation; + + str += "\n Type param bounds: "; + if (!has_type_param_bounds ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + str += "\n " + bound->as_string (); + } + } + + str += "\n Type: "; + if (!has_type ()) + { + str += "none"; + } + else + { + str += type->as_string (); + } + + return str; +} + +SimplePath +PathPattern::convert_to_simple_path (bool with_opening_scope_resolution) const +{ + if (!has_segments ()) + { + return SimplePath::create_empty (); + } + + // create vector of reserved size (to minimise reallocations) + std::vector 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 simple_segments; + simple_segments.reserve (segments.size ()); + + for (const auto &segment : segments) + { + // return empty path if doesn't meet simple path segment requirements + if (segment == nullptr || segment->is_error () + || !segment->is_ident_only () || segment->as_string () == "Self") + { + return SimplePath::create_empty (); + } + + // create segment and add to vector + std::string segment_str = segment->as_string (); + simple_segments.push_back ( + SimplePathSegment (std::move (segment_str), segment->get_locus ())); + } + + return SimplePath (std::move (simple_segments), has_opening_scope_resolution, + locus); +} + +std::string +PathExprSegment::as_string () const +{ + std::string ident_str = segment_name.as_string (); + if (has_generic_args ()) + { + ident_str += "::<" + generic_args.as_string () + ">"; + } + + return ident_str; +} + +std::string +GenericArgs::as_string () const +{ + std::string args; + + // lifetime args + if (!lifetime_args.empty ()) + { + auto i = lifetime_args.begin (); + auto e = lifetime_args.end (); + + for (; i != e; i++) + { + args += (*i).as_string (); + if (e != i + 1) + args += ", "; + } + } + + // type args + if (!type_args.empty ()) + { + auto i = type_args.begin (); + auto e = type_args.end (); + + for (; i != e; i++) + { + args += (*i)->as_string (); + if (e != i + 1) + args += ", "; + } + } + + // binding args + if (!binding_args.empty ()) + { + auto i = binding_args.begin (); + auto e = binding_args.end (); + + for (; i != e; i++) + { + args += (*i).as_string (); + if (e != i + 1) + args += ", "; + } + } + + return args; +} + +std::string +GenericArgsBinding::as_string () const +{ + return identifier + " = " + type->as_string (); +} + +std::string +ForLoopExpr::as_string () const +{ + std::string str ("ForLoopExpr: "); + + str += "\n Label: "; + if (!has_loop_label ()) + { + str += "none"; + } + else + { + str += loop_label.as_string (); + } + + str += "\n Pattern: " + pattern->as_string (); + + str += "\n Iterator expr: " + iterator_expr->as_string (); + + str += "\n Loop block: " + loop_block->as_string (); + + return str; +} + +std::string +RangePattern::as_string () const +{ + if (has_ellipsis_syntax) + { + return lower->as_string () + "..." + upper->as_string (); + } + else + { + return lower->as_string () + "..=" + upper->as_string (); + } +} + +std::string +RangePatternBoundLiteral::as_string () const +{ + std::string str; + + if (has_minus) + { + str += "-"; + } + + str += literal.as_string (); + + return str; +} + +std::string +SlicePattern::as_string () const +{ + std::string str ("SlicePattern: "); + + for (const auto &pattern : items) + { + str += "\n " + pattern->as_string (); + } + + return str; +} + +std::string +TuplePatternItemsMultiple::as_string () const +{ + std::string str; + + for (const auto &pattern : patterns) + { + str += "\n " + pattern->as_string (); + } + + return str; +} + +std::string +TuplePatternItemsRanged::as_string () const +{ + std::string str; + + str += "\n Lower patterns: "; + if (lower_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &lower : lower_patterns) + { + str += "\n " + lower->as_string (); + } + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &upper : upper_patterns) + { + str += "\n " + upper->as_string (); + } + } + + return str; +} + +std::string +TuplePattern::as_string () const +{ + return "TuplePattern: " + items->as_string (); +} + +std::string +StructPatternField::as_string () const +{ + // outer attributes + std::string str ("Outer attributes: "); + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + return str; +} + +std::string +StructPatternFieldIdent::as_string () const +{ + std::string str = StructPatternField::as_string (); + + str += "\n"; + + if (has_ref) + { + str += "ref "; + } + + if (has_mut) + { + str += "mut "; + } + + str += ident; + + return str; +} + +std::string +StructPatternFieldTuplePat::as_string () const +{ + std::string str = StructPatternField::as_string (); + + str += "\n"; + + str += std::to_string (index) + " : " + tuple_pattern->as_string (); + + return str; +} + +std::string +StructPatternFieldIdentPat::as_string () const +{ + std::string str = StructPatternField::as_string (); + + str += "\n"; + + str += ident + " : " + ident_pattern->as_string (); + + return str; +} + +std::string +StructPatternElements::as_string () const +{ + std::string str ("\n Fields: "); + + if (!has_struct_pattern_fields ()) + { + str += "none"; + } + else + { + for (const auto &field : fields) + { + str += "\n " + field->as_string (); + } + } + + str += "\n Etc: "; + if (has_struct_pattern_etc) + { + str += "true"; + } + else + { + str += "false"; + } + + return str; +} + +std::string +StructPattern::as_string () const +{ + std::string str ("StructPattern: \n Path: "); + + str += path.as_string (); + + str += "\n Struct pattern elems: "; + if (!has_struct_pattern_elems ()) + { + str += "none"; + } + else + { + str += elems.as_string (); + } + + return str; +} + +std::string +LiteralPattern::as_string () const +{ + std::string str; + + if (has_minus) + { + str += "-"; + } + + return str + lit.as_string (); +} + +std::string +ReferencePattern::as_string () const +{ + std::string str ("&"); + + if (has_two_amps) + { + str += "&"; + } + + if (is_mut) + { + str += "mut "; + } + + str += pattern->as_string (); + + return str; +} + +std::string +IdentifierPattern::as_string () const +{ + std::string str; + + if (is_ref) + { + str += "ref "; + } + + if (is_mut) + { + str += "mut "; + } + + str += variable_ident; + + if (has_pattern_to_bind ()) + { + str += " @ " + to_bind->as_string (); + } + + return str; +} + +std::string +TupleStructItemsNoRange::as_string () const +{ + std::string str; + + for (const auto &pattern : patterns) + { + str += "\n " + pattern->as_string (); + } + + return str; +} + +std::string +TupleStructItemsRange::as_string () const +{ + std::string str ("\n Lower patterns: "); + + if (lower_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &lower : lower_patterns) + { + str += "\n " + lower->as_string (); + } + } + + str += "\n Upper patterns: "; + if (upper_patterns.empty ()) + { + str += "none"; + } + else + { + for (const auto &upper : upper_patterns) + { + str += "\n " + upper->as_string (); + } + } + + return str; +} + +std::string +TupleStructPattern::as_string () const +{ + std::string str ("TupleStructPattern: \n Path: "); + + str += path.as_string (); + + str += "\n Tuple struct items: " + items->as_string (); + + return str; +} + +std::string +LetStmt::as_string () const +{ + // outer attributes + std::string str = "Outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + indent_spaces (enter); + for (const auto &attr : outer_attrs) + { + str += "\n" + indent_spaces (stay) + attr.as_string (); + } + indent_spaces (out); + } + + str += "\n" + indent_spaces (stay) + "let " + variables_pattern->as_string (); + + if (has_type ()) + { + str += " : " + type->as_string (); + } + + if (has_init_expr ()) + { + str += " = " + init_expr->as_string (); + } + + return str; +} + +// Used to get outer attributes for expressions. +std::string +Expr::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + return str; +} + +// hopefully definition here will prevent circular dependency issue +TraitBound * +TypePath::to_trait_bound (bool in_parens) const +{ + // create clone FIXME is this required? or is copy constructor automatically + // called? + TypePath copy (*this); + return new TraitBound (std::move (copy), copy.get_locus (), in_parens); +} + +std::string +InferredType::as_string () const +{ + return "_ (inferred)"; +} + +std::string +TypeCastExpr::as_string () const +{ + return main_or_left_expr->as_string () + " as " + + type_to_convert_to->as_string (); +} + +std::string +ImplTraitType::as_string () const +{ + std::string str ("ImplTraitType: \n TypeParamBounds: "); + + if (type_param_bounds.empty ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + str += "\n " + bound->as_string (); + } + } + + return str; +} + +std::string +ReferenceType::as_string () const +{ + std::string str ("&"); + + if (has_lifetime ()) + { + str += lifetime.as_string () + " "; + } + + if (has_mut) + { + str += "mut "; + } + + str += type->as_string (); + + return str; +} + +std::string +RawPointerType::as_string () const +{ + std::string str ("*"); + + switch (pointer_type) + { + case MUT: + str += "mut "; + break; + case CONST: + str += "const "; + break; + default: + return "ERROR_MARK_STRING - unknown pointer type in raw pointer type"; + } + + str += type->as_string (); + + return str; +} + +std::string +TraitObjectType::as_string () const +{ + std::string str ("TraitObjectType: \n Has dyn dispatch: "); + + if (has_dyn) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n TypeParamBounds: "; + if (type_param_bounds.empty ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + str += "\n " + bound->as_string (); + } + } + + return str; +} + +std::string +BareFunctionType::as_string () const +{ + std::string str ("BareFunctionType: \n For lifetimes: "); + + if (!has_for_lifetimes ()) + { + str += "none"; + } + else + { + for (const auto &for_lifetime : for_lifetimes) + { + str += "\n " + for_lifetime.as_string (); + } + } + + str += "\n Qualifiers: " + function_qualifiers.as_string (); + + str += "\n Params: "; + if (params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : params) + { + str += "\n " + param.as_string (); + } + } + + str += "\n Is variadic: "; + if (is_variadic) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n Return type: "; + if (!has_return_type ()) + { + str += "none (void)"; + } + else + { + str += return_type->as_string (); + } + + return str; +} + +std::string +ImplTraitTypeOneBound::as_string () const +{ + std::string str ("ImplTraitTypeOneBound: \n TraitBound: "); + + return str + trait_bound.as_string (); +} + +std::string +TypePathSegmentGeneric::as_string () const +{ + return TypePathSegment::as_string () + "<" + generic_args.as_string () + ">"; +} + +std::string +TraitObjectTypeOneBound::as_string () const +{ + std::string str ("TraitObjectTypeOneBound: \n Has dyn dispatch: "); + + if (has_dyn) + { + str += "true"; + } + else + { + str += "false"; + } + + str += "\n TraitBound: " + trait_bound.as_string (); + + return str; +} + +std::string +TypePathFunction::as_string () const +{ + std::string str ("("); + + if (has_inputs ()) + { + auto i = inputs.begin (); + auto e = inputs.end (); + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + } + + str += ")"; + + if (has_return_type ()) + { + str += " -> " + return_type->as_string (); + } + + return str; +} + +std::string +TypePathSegmentFunction::as_string () const +{ + return TypePathSegment::as_string () + function_path.as_string (); +} + +std::string +ArrayType::as_string () const +{ + return "[" + elem_type->as_string () + "; " + size->as_string () + "]"; +} + +std::string +SliceType::as_string () const +{ + return "[" + elem_type->as_string () + "]"; +} + +std::string +TupleType::as_string () const +{ + std::string str ("("); + + if (!is_unit_type ()) + { + auto i = elems.begin (); + auto e = elems.end (); + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + } + + str += ")"; + + return str; +} + +std::string +StructExpr::as_string () const +{ + std::string str = ExprWithoutBlock::as_string (); + indent_spaces (enter); + str += "\n" + indent_spaces (stay) + "StructExpr:"; + indent_spaces (enter); + str += "\n" + indent_spaces (stay) + "PathInExpr:\n"; + str += indent_spaces (stay) + struct_name.as_string (); + indent_spaces (out); + indent_spaces (out); + return str; +} + +std::string +StructExprTuple::as_string () const +{ + std::string str = StructExpr::as_string (); + + if (exprs.empty ()) + { + str += "()"; + } + else + { + auto i = exprs.begin (); + auto e = exprs.end (); + + // debug - null pointer check + if (*i == nullptr) + { + return "ERROR_MARK_STRING - nullptr struct expr tuple field"; + } + + str += '('; + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + str += ')'; + } + + indent_spaces (enter); + indent_spaces (enter); + // inner attributes + str += "\n" + indent_spaces (stay) + "inner attributes:"; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n" + indent_spaces (stay) + attr.as_string (); + } + } + indent_spaces (out); + indent_spaces (out); + + return str; +} + +std::string +StructExprStruct::as_string () const +{ + std::string str ("StructExprStruct (or subclass): "); + + str += "\n Path: " + get_struct_name ().as_string (); + + // inner attributes + str += "\n inner attributes: "; + if (inner_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "inner attribute" syntax - + * just the body */ + for (const auto &attr : inner_attrs) + { + str += "\n " + attr.as_string (); + } + } + + return str; +} + +std::string +StructBase::as_string () const +{ + if (base_struct != nullptr) + { + return base_struct->as_string (); + } + else + { + return "ERROR_MARK_STRING - invalid struct base had as string applied"; + } +} + +std::string +StructExprFieldWithVal::as_string () const +{ + // used to get value string + return value->as_string (); +} + +std::string +StructExprFieldIdentifierValue::as_string () const +{ + return field_name + " : " + StructExprFieldWithVal::as_string (); +} + +std::string +StructExprFieldIndexValue::as_string () const +{ + return std::to_string (index) + " : " + StructExprFieldWithVal::as_string (); +} + +std::string +StructExprStructFields::as_string () const +{ + std::string str = StructExprStruct::as_string (); + + str += "\n Fields: "; + if (fields.empty ()) + { + str += "none"; + } + else + { + for (const auto &field : fields) + { + str += "\n " + field->as_string (); + } + } + + str += "\n Struct base: "; + if (!has_struct_base ()) + { + str += "none"; + } + else + { + str += struct_base.as_string (); + } + + return str; +} + +std::string +EnumItem::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n" + variant_name; + + return str; +} + +std::string +EnumItemTuple::as_string () const +{ + std::string str = EnumItem::as_string (); + + // add tuple opening parens + str += "("; + + // tuple fields + if (has_tuple_fields ()) + { + auto i = tuple_fields.begin (); + auto e = tuple_fields.end (); + + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + } + + // add tuple closing parens + str += ")"; + + return str; +} + +std::string +TupleField::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + if (has_visibility ()) + { + str += "\n" + visibility.as_string (); + } + + str += " " + field_type->as_string (); + + return str; +} + +std::string +EnumItemStruct::as_string () const +{ + std::string str = EnumItem::as_string (); + + // add struct opening parens + str += "{"; + + // tuple fields + if (has_struct_fields ()) + { + auto i = struct_fields.begin (); + auto e = struct_fields.end (); + + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + } + + // add struct closing parens + str += "}"; + + return str; +} + +std::string +StructField::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + if (has_visibility ()) + { + str += "\n" + visibility.as_string (); + } + + str += " " + field_name + " : " + field_type->as_string (); + + return str; +} + +std::string +EnumItemDiscriminant::as_string () const +{ + std::string str = EnumItem::as_string (); + + // add equal and expression + str += " = " + expression->as_string (); + + return str; +} + +std::string +ExternalItem::as_string () const +{ + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + // start visibility on new line and with a space + str += "\n" + visibility.as_string () + " "; + + return str; +} + +std::string +ExternalStaticItem::as_string () const +{ + std::string str = ExternalItem::as_string (); + + str += "static "; + + if (has_mut) + { + str += "mut "; + } + + // add name + str += get_item_name (); + + // add type on new line + str += "\n Type: " + item_type->as_string (); + + return str; +} + +std::string +ExternalFunctionItem::as_string () const +{ + std::string str = ExternalItem::as_string (); + + str += "fn "; + + // add name + str += get_item_name (); + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in external function item."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + // function params + str += "\n Function params: "; + if (function_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : function_params) + { + str += "\n " + param.as_string (); + } + if (has_variadics) + { + str += "\n .. (variadic)"; + } + } + + // add type on new line + str += "\n (return) Type: " + return_type->as_string (); + + // where clause + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +NamedFunctionParam::as_string () const +{ + std::string str = name; + + str += "\n Type: " + param_type->as_string (); + + return str; +} + +/*std::string TraitItem::as_string() const { + // outer attributes + std::string str = "outer attributes: "; + if (outer_attrs.empty()) { + str += "none"; + } else { + // note that this does not print them with "outer attribute" syntax - +just the body for (const auto& attr : outer_attrs) { str += "\n " + +attr.as_string(); + } + } + + return str; +}*/ + +std::string +TraitItemFunc::as_string () const +{ + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n" + decl.as_string (); + + str += "\n Definition (block expr): "; + if (has_definition ()) + { + str += block_expr->as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +TraitFunctionDecl::as_string () const +{ + std::string str = qualifiers.as_string () + "fn " + function_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in trait function decl."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Function params: "; + if (has_params ()) + { + for (const auto ¶m : function_params) + { + str += "\n " + param.as_string (); + } + } + else + { + str += "none"; + } + + str += "\n Return type: "; + if (has_return_type ()) + { + str += return_type->as_string (); + } + else + { + str += "none (void)"; + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +TraitItemMethod::as_string () const +{ + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\n" + decl.as_string (); + + str += "\n Definition (block expr): "; + if (has_definition ()) + { + str += block_expr->as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +TraitMethodDecl::as_string () const +{ + std::string str = qualifiers.as_string () + "fn " + function_name; + + // generic params + str += "\n Generic params: "; + if (generic_params.empty ()) + { + str += "none"; + } + else + { + for (const auto ¶m : generic_params) + { + // DEBUG: null pointer check + if (param == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "generic param in trait function decl."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + param->as_string (); + } + } + + str += "\n Self param: " + self_param.as_string (); + + str += "\n Function params: "; + if (has_params ()) + { + for (const auto ¶m : function_params) + { + str += "\n " + param.as_string (); + } + } + else + { + str += "none"; + } + + str += "\n Return type: "; + if (has_return_type ()) + { + str += return_type->as_string (); + } + else + { + str += "none (void)"; + } + + str += "\n Where clause: "; + if (has_where_clause ()) + { + str += where_clause.as_string (); + } + else + { + str += "none"; + } + + return str; +} + +std::string +TraitItemConst::as_string () const +{ + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\nconst " + name + " : " + type->as_string (); + + if (has_expression ()) + { + str += " = " + expr->as_string (); + } + + return str; +} + +std::string +TraitItemType::as_string () const +{ + std::string str = "outer attributes: "; + if (outer_attrs.empty ()) + { + str += "none"; + } + else + { + /* note that this does not print them with "outer attribute" syntax - + * just the body */ + for (const auto &attr : outer_attrs) + { + str += "\n " + attr.as_string (); + } + } + + str += "\ntype " + name; + + str += "\n Type param bounds: "; + if (!has_type_param_bounds ()) + { + str += "none"; + } + else + { + for (const auto &bound : type_param_bounds) + { + // DEBUG: null pointer check + if (bound == nullptr) + { + fprintf ( + stderr, + "something really terrible has gone wrong - null pointer " + "type param bound in trait item type."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + bound->as_string (); + } + } + + return str; +} + +std::string +SelfParam::as_string () const +{ + if (is_error ()) + { + return "error"; + } + else + { + if (has_type ()) + { + // type (i.e. not ref, no lifetime) + std::string str; + + if (is_mut) + { + str += "mut "; + } + + str += "self : "; + + str += type->as_string (); + + return str; + } + else if (has_lifetime ()) + { + // ref and lifetime + std::string str = "&" + lifetime.as_string () + " "; + + if (is_mut) + { + str += "mut "; + } + + str += "self"; + + return str; + } + else if (has_ref) + { + // ref with no lifetime + std::string str = "&"; + + if (is_mut) + { + str += " mut "; + } + + str += "self"; + + return str; + } + else + { + // no ref, no type + std::string str; + + if (is_mut) + { + str += "mut "; + } + + str += "self"; + + return str; + } + } +} + +std::string +ArrayElemsCopied::as_string () const +{ + return elem_to_copy->as_string () + "; " + num_copies->as_string (); +} + +std::string +LifetimeWhereClauseItem::as_string () const +{ + std::string str ("Lifetime: "); + + str += lifetime.as_string (); + + str += "\nLifetime bounds: "; + + for (const auto &bound : lifetime_bounds) + { + str += "\n " + bound.as_string (); + } + + return str; +} + +std::string +TypeBoundWhereClauseItem::as_string () const +{ + std::string str ("For lifetimes: "); + + if (!has_for_lifetimes ()) + { + str += "none"; + } + else + { + for (const auto &for_lifetime : for_lifetimes) + { + str += "\n " + for_lifetime.as_string (); + } + } + + str += "\nType: " + bound_type->as_string (); + + str += "\nType param bounds bounds: "; + + for (const auto &bound : type_param_bounds) + { + // debug null pointer check + if (bound == nullptr) + { + return "nullptr_POINTER_MARK - type param bounds"; + } + + str += "\n " + bound->as_string (); + } + + return str; +} + +std::string +ArrayElemsValues::as_string () const +{ + std::string str; + + for (const auto &expr : values) + { + // DEBUG: null pointer check + if (expr == nullptr) + { + fprintf (stderr, + "something really terrible has gone wrong - null pointer " + "expr in array elems values."); + return "nullptr_POINTER_MARK"; + } + + str += "\n " + expr->as_string (); + } + + return str; +} + +std::string +MaybeNamedParam::as_string () const +{ + std::string str; + + switch (param_kind) + { + case UNNAMED: + break; + case IDENTIFIER: + str = name + " : "; + break; + case WILDCARD: + str = "_ : "; + break; + default: + return "ERROR_MARK_STRING - maybe named param unrecognised param kind"; + } + + str += param_type->as_string (); + + return str; +} + +std::string +MetaItemSeq::as_string () const +{ + std::string path_str = path.as_string () + "("; + + auto i = seq.begin (); + auto e = seq.end (); + + for (; i != e; i++) + { + path_str += (*i)->as_string (); + if (e != i + 1) + path_str += ", "; + } + + return path_str + ")"; +} + +std::string +MetaListPaths::as_string () const +{ + std::string str = ident + "("; + + auto i = paths.begin (); + auto e = paths.end (); + + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + + return str + ")"; +} + +std::string +MetaListNameValueStr::as_string () const +{ + std::string str = ident + "("; + + auto i = strs.begin (); + auto e = strs.end (); + + for (; i != e; i++) + { + str += (*i).as_string (); + if (e != i + 1) + str += ", "; + } + + return str + ")"; +} + +std::string +AttrInputMetaItemContainer::as_string () const +{ + std::string str = "("; + + auto i = items.begin (); + auto e = items.end (); + + for (; i != e; i++) + { + str += (*i)->as_string (); + if (e != i + 1) + str += ", "; + } + + return str + ")"; +} + +/* Override that calls the function recursively on all items contained within + * the module. */ +void +ModuleBodied::add_crate_name (std::vector &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 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 > token_stream = to_token_stream (); + + MacroParser parser (std::move (token_stream)); + std::vector > meta_items ( + parser.parse_meta_item_seq ()); + + return new AttrInputMetaItemContainer (std::move (meta_items)); +} + +std::unique_ptr +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 (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 ( + 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 > meta_items + = parse_meta_item_seq (); + + // pass for meta name value str + std::vector meta_name_value_str_items; + for (const auto &item : meta_items) + { + std::unique_ptr 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 ( + new MetaListNameValueStr (std::move (ident), + std::move (meta_name_value_str_items))); + } + + // pass for meta list idents + /*std::vector ident_items; + for (const auto& item : meta_items) { + std::unique_ptr 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(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 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 ( + 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 +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 > meta_items + = parse_meta_item_seq (); + + return std::unique_ptr ( + 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 ( + new MetaItemPathLit (std::move (path), std::move (expr))); + } + case COMMA: + // just simple path + return std::unique_ptr ( + 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 > +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 > 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 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 > +DelimTokenTree::to_token_stream () const +{ + std::vector > tokens; + + // simulate presence of delimiters + tokens.push_back ( + std::unique_ptr (new Token (LEFT_PAREN, Linemap::unknown_location (), + "", CORETYPE_UNKNOWN))); + + for (const auto &tree : token_trees) + { + std::vector > 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 ( + new Token (RIGHT_PAREN, Linemap::unknown_location (), "", + CORETYPE_UNKNOWN))); + + tokens.shrink_to_fit (); + + return tokens; +} + +Literal +MacroParser::parse_literal () +{ + const std::unique_ptr &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 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 &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 +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 ( + new MetaItemLitExpr (std::move (lit_expr))); +} + +std::vector > +Token::to_token_stream () const +{ + /* initialisation list doesn't work as it needs copy constructor, so have to + * do this */ + std::vector > dummy_vector; + dummy_vector.reserve (1); + dummy_vector.push_back (std::unique_ptr (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 ( + new AttrInputLiteral (std::move (lit_expr)))); +} + +Attribute +MetaItemPath::to_attribute () const +{ + return Attribute (path, nullptr); +} + +Attribute +MetaItemSeq::to_attribute () const +{ + std::vector > new_seq; + new_seq.reserve (seq.size ()); + for (const auto &e : seq) + new_seq.push_back (e->clone_meta_item_inner ()); + + std::unique_ptr 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 > new_seq; + new_seq.reserve (paths.size ()); + for (const auto &e : paths) + new_seq.push_back (std::unique_ptr (new MetaItemPath (e))); + + std::unique_ptr 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 > new_seq; + new_seq.reserve (strs.size ()); + for (const auto &e : strs) + new_seq.push_back ( + std::unique_ptr (new MetaNameValueStr (e))); + + std::unique_ptr 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 ( + 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 +// . + +#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..774e407 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -0,0 +1,3293 @@ +// 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 +// . + +#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 outer_attr; + Attribute outer_attr; + + Identifier type_representation; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + std::vector > + type_param_bounds; // inlined form + + // bool has_type; + std::unique_ptr 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 > type_param_bounds + = std::vector > (), + std::unique_ptr 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 clone_where_clause_item () const + { + return std::unique_ptr (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_bounds; // inlined lifetime bounds + + // should this store location info? + +public: + LifetimeWhereClauseItem (Lifetime lifetime, + std::vector 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 for_lifetimes; // inlined + + std::unique_ptr bound_type; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + std::vector > + 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 for_lifetimes, std::unique_ptr bound_type, + std::vector > 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 > where_clause_items; + + // should this store location info? + +public: + WhereClause ( + std::vector > 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 > ()); + } + + // 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; + + 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 + } + + // Creates an error state self-param. + static SelfParam create_error () + { + /* HACK: creates a dummy type. Since it's a unique pointer, it should + * clean it up, but it still allocates memory, which is not ideal. */ + return SelfParam (Lifetime (Lifetime::STATIC), false, false, + new QualifiedPathInType ( + QualifiedPathInType::create_error ())); + /* FIXME: is there a reason why I didn't just create a null pointer? Is it + * due to error being having both a type and a lifetime? If it is, wouldn't + * something like "not has_ref and has lifetime" for error be better? */ + } + + // Type-based self parameter (not ref, no lifetime) + SelfParam (std::unique_ptr 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 param_name; + std::unique_ptr type; + + Location locus; + + FunctionParam (std::unique_ptr param_name, + std::unique_ptr param_type, Location locus) + : param_name (std::move (param_name)), type (std::move (param_type)), + locus (locus) + {} + + // Copy constructor uses clone + FunctionParam (FunctionParam const &other) + : param_name (other.param_name->clone_pattern ()), + type (other.type->clone_type ()), locus (other.locus) + {} + + // 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; + + return *this; + } + + // move constructors + FunctionParam (FunctionParam &&other) = default; + FunctionParam &operator= (FunctionParam &&other) = default; + + // Returns whether FunctionParam is in an invalid state. + bool is_error () const { return param_name == nullptr || type == nullptr; } + + // Creates an error FunctionParam. + static FunctionParam create_error () + { + return FunctionParam (nullptr, nullptr, Location ()); + } + + 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 (); } +}; + +// 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 clone_visibility() const { + return std::unique_ptr(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 outer_attrs; + Visibility vis; + + FunctionQualifiers qualifiers; + Identifier method_name; + + // bool has_generics; + // Generics generic_params; + std::vector > generic_params; // inlined + + SelfParam self_param; + + // bool has_params; + // FunctionParams function_params; + std::vector function_params; // inlined + + // bool has_return_type; + // FunctionReturnType return_type; + std::unique_ptr return_type; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::unique_ptr expr; + + Location locus; + +public: + // Returns whether the method is in an error state. + bool is_error () const + { + return expr == nullptr || method_name.empty () || self_param.is_error (); + } + + // Creates an error state method. + static Method create_error () + { + return Method ("", FunctionQualifiers (FunctionQualifiers::NONE, true), + std::vector > (), + SelfParam::create_error (), std::vector (), + nullptr, WhereClause::create_empty (), nullptr, + Visibility::create_error (), std::vector ()); + } + + // 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 > generic_params, + SelfParam self_param, std::vector function_params, + std::unique_ptr return_type, WhereClause where_clause, + std::unique_ptr function_body, Visibility vis, + std::vector 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 outer_attrs = std::vector ()) + : 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 outer_attrs = std::vector ()) + : 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 inner_attrs; + // bool has_items; + std::vector > 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 > items + = std::vector > (), + Visibility visibility = Visibility::create_error (), + std::vector inner_attrs = std::vector (), + std::vector outer_attrs = std::vector ()) + : 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 &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 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 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 &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 clone_use_tree () const + { + return std::unique_ptr (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 > trees; + +public: + UseTreeList (PathType path_type, SimplePath path, + std::vector > 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 use_tree; + Location locus; + +public: + std::string as_string () const override; + + UseDeclaration (Analysis::NodeMapping mappings, + std::unique_ptr use_tree, Visibility visibility, + std::vector 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 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 > generic_params; // inlined + + // bool has_function_params; + // FunctionParams function_params; + std::vector function_params; // inlined + + // bool has_function_return_type; + std::unique_ptr return_type; + + // bool has_where_clause; + WhereClause where_clause; + + std::unique_ptr function_body; + + Location locus; + + std::vector locals; + + 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 > generic_params, + std::vector function_params, + std::unique_ptr return_type, WhereClause where_clause, + std::unique_ptr function_body, Visibility vis, + std::vector 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 > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::unique_ptr 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 > generic_params, + WhereClause where_clause, std::unique_ptr existing_type, + Visibility vis, std::vector 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 > 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 > generic_params, + WhereClause where_clause, Visibility vis, Location locus, + std::vector outer_attrs = std::vector ()) + : 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 outer_attrs; + + // bool has_visibility; + Visibility visibility; + + Identifier field_name; + std::unique_ptr 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 field_type, + Visibility vis, + std::vector outer_attrs = std::vector ()) + : 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 fields; + bool is_unit; + + std::string as_string () const override; + + // Mega-constructor with all possible fields + StructStruct (Analysis::NodeMapping mappings, std::vector fields, + Identifier struct_name, + std::vector > generic_params, + WhereClause where_clause, bool is_unit, Visibility vis, + std::vector 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 > generic_params, + WhereClause where_clause, Visibility vis, + std::vector 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 outer_attrs; + + // bool has_visibility; + Visibility visibility; + + std::unique_ptr 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 field_type, Visibility vis, + std::vector outer_attrs = std::vector ()) + : 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 fields; + +public: + std::string as_string () const override; + + // Mega-constructor with all possible fields + TupleStruct (Analysis::NodeMapping mappings, std::vector fields, + Identifier struct_name, + std::vector > generic_params, + WhereClause where_clause, Visibility vis, + std::vector 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 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 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 clone_enum_item () const + { + return std::unique_ptr (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 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 tuple_fields, + std::vector 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 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 struct_fields, + std::vector 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 expression; + +public: + EnumItemDiscriminant (Identifier variant_name, std::unique_ptr expr, + std::vector 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 > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::vector > 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 > generic_params, + WhereClause where_clause, std::vector > items, + std::vector 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 > generic_params; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::vector 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 > generic_params, + WhereClause where_clause, std::vector variants, + std::vector 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; + std::unique_ptr const_expr; + + Location locus; + +public: + std::string as_string () const override; + + ConstantItem (Analysis::NodeMapping mappings, Identifier ident, + Visibility vis, std::unique_ptr type, + std::unique_ptr const_expr, + std::vector 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; + std::unique_ptr expr; + Location locus; + +public: + std::string as_string () const override; + + StaticItem (Analysis::NodeMapping mappings, Identifier name, bool is_mut, + std::unique_ptr type, std::unique_ptr expr, + Visibility vis, std::vector 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 > generic_params; // inlined + + // bool has_params; + // FunctionParams function_params; + std::vector function_params; // inlined + + // bool has_return_type; + std::unique_ptr 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 > generic_params, + std::vector function_params, + std::unique_ptr 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 outer_attrs; + TraitFunctionDecl decl; + std::unique_ptr 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 block_expr, + std::vector 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 > generic_params; // inlined + + SelfParam self_param; + + // bool has_params; + // FunctionParams function_params; + std::vector function_params; // inlined + + // bool has_return_type; + std::unique_ptr 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 > generic_params, + SelfParam self_param, + std::vector function_params, + std::unique_ptr 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 outer_attrs; + TraitMethodDecl decl; + std::unique_ptr 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 block_expr, + std::vector 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 outer_attrs; + Identifier name; + std::unique_ptr type; + + // bool has_expression; + std::unique_ptr 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, + std::unique_ptr expr, + std::vector 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 outer_attrs; + + Identifier name; + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + std::vector > + 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 > type_param_bounds, + std::vector 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 > generic_params; // inlined + + // bool has_type_param_bounds; + // TypeParamBounds type_param_bounds; + std::vector > + type_param_bounds; // inlined form + + // bool has_where_clause; + WhereClause where_clause; + + // bool has_trait_items; + std::vector > 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 > generic_params, + std::vector > type_param_bounds, + WhereClause where_clause, + std::vector > trait_items, Visibility vis, + std::vector 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 > generic_params; // inlined + + std::unique_ptr trait_type; + + // bool has_where_clause; + WhereClause where_clause; + + // bool has_inner_attrs; + std::vector 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 > generic_params, + std::unique_ptr trait_type, WhereClause where_clause, + Visibility vis, std::vector inner_attrs, + std::vector 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 > 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 > impl_items, + std::vector > generic_params, + std::unique_ptr trait_type, WhereClause where_clause, + Visibility vis, std::vector inner_attrs, + std::vector 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 > 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 > impl_items, + std::vector > generic_params, + std::unique_ptr trait_type, WhereClause where_clause, + Visibility vis, std::vector inner_attrs, + std::vector 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 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 clone_external_item () const + { + return std::unique_ptr (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 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 item_type; + +public: + ExternalStaticItem (Identifier item_name, std::unique_ptr item_type, + bool is_mut, Visibility vis, + std::vector 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 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 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 > generic_params; // inlined + + // bool has_return_type; + // FunctionReturnType return_type; + std::unique_ptr return_type; // inlined + + // bool has_where_clause; + WhereClause where_clause; + + std::vector 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 > generic_params, + std::unique_ptr return_type, WhereClause where_clause, + std::vector function_params, bool has_variadics, + Visibility vis, std::vector 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 inner_attrs; + + // bool has_extern_items; + std::vector > 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 > extern_items, + Visibility vis, std::vector inner_attrs, + std::vector 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..0a38134 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-macro.h @@ -0,0 +1,627 @@ +// 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 +// . + +#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 > matches; + MacroRepOp op; + + // bool has_sep; + typedef Token MacroRepSep; + // any token except delimiters and repetition operators + std::unique_ptr 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 > matches, + MacroRepOp op, std::unique_ptr 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 > 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 > 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 rules; // inlined form + + Location locus; + +public: + std::string as_string () const override; + + MacroRulesDefinition (Analysis::NodeMapping mappings, Identifier rule_name, + DelimType delim_type, std::vector rules, + std::vector 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 outer_attrs, Location locus) + : 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 > seq; + +public: + MetaItemSeq (SimplePath path, + std::vector > 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 to_meta_name_value_str () const override + { + return std::unique_ptr (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 paths; + +public: + MetaListPaths (Identifier ident, std::vector 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 strs; + +public: + MetaListNameValueStr (Identifier ident, std::vector 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 > 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 > token_stream, + int stream_start_pos = 0) + : token_stream (std::move (token_stream)), stream_pos (stream_start_pos) + {} + + ~MacroParser () = default; + + std::vector > parse_meta_item_seq (); + +private: + // Parses a MetaItemInner. + std::unique_ptr 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 parse_meta_item_lit (); + // Parses a literal. + Literal parse_literal (); + // Parses a meta item that begins with a simple path. + std::unique_ptr parse_path_meta_item (); + + // TODO: should this be const? + std::unique_ptr &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..06d31aa --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -0,0 +1,850 @@ +// 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 +// . + +#ifndef RUST_HIR_PATH_H +#define RUST_HIR_PATH_H + +#include "rust-hir.h" + +#include +#include + +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; + + 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_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_args; + std::vector > type_args; + std::vector 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_args, + std::vector > type_args, + std::vector 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 (), + std::vector > (), + std::vector ()); + } + + 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_args + = std::vector (), + std::vector > type_args + = std::vector > (), + std::vector binding_args + = std::vector ()) + : 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 segments; + +protected: + PathPattern (std::vector 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 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 path_segments, + Location locus = Location (), + bool has_opening_scope_resolution = false, + std::vector outer_attrs + = std::vector ()) + : 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 ()); + } + + // 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 clone_type_path_segment () const + { + return std::unique_ptr (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_args, + std::vector > type_args, + std::vector 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 > inputs; + + // bool has_type; + std::unique_ptr 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 > inputs, + Type *type = nullptr) + : inputs (std::move (inputs)), return_type (type), is_invalid (false) + {} + // FIXME: deprecated + + // Constructor + TypePathFunction (std::vector > inputs, + std::unique_ptr 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 > 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 (std::vector > (), + Location ()); + } + + // Constructor + TypePath (std::vector > segments, + Location locus, bool has_opening_scope_resolution = false) + : has_opening_scope_resolution (has_opening_scope_resolution), + segments (std::move (segments)), locus (locus) + {} + + // Copy constructor with vector clone + TypePath (TypePath const &other) + : has_opening_scope_resolution (other.has_opening_scope_resolution), + locus (other.locus) + { + 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; + + 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 cb) + { + for (auto it = segments.begin (); it != segments.end (); it++) + { + if (!cb ((*it).get ())) + return; + } + } +}; + +struct QualifiedPathType +{ +private: + std::unique_ptr type_to_invoke_on; + + // bool has_as_clause; + TypePath trait_path; + + Location locus; + +public: + // Constructor + QualifiedPathType (std::unique_ptr 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 path_segments, + Location locus = Location (), + std::vector outer_attrs + = std::vector ()) + : 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 ()); + } + + 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 > 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 ( + QualifiedPathType qual_path_type, + std::vector > path_segments, + Location locus = Location ()) + : path_type (std::move (qual_path_type)), + segments (std::move (path_segments)), locus (locus) + {} + + /* TODO: maybe make a shortcut constructor that has QualifiedPathType elements + * as params */ + + // Copy constructor with vector clone + QualifiedPathInType (QualifiedPathInType const &other) + : path_type (other.path_type), locus (other.locus) + { + 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; + + segments.reserve (other.segments.size ()); + for (const auto &e : other.segments) + segments.push_back (e->clone_type_path_segment ()); + + return *this; + } + + // move constructors + QualifiedPathInType (QualifiedPathInType &&other) = default; + QualifiedPathInType &operator= (QualifiedPathInType &&other) = default; + + // Returns whether qualified path in type is in an error state. + bool is_error () const { return path_type.is_error (); } + + // Creates an error state qualified path in type. + static QualifiedPathInType create_error () + { + return QualifiedPathInType ( + QualifiedPathType::create_error (), + std::vector > ()); + } + + std::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 +// . + +#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 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 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 clone_range_pattern_bound () const + { + return std::unique_ptr ( + 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 lower; + std::unique_ptr 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 lower, + std::unique_ptr 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; + Location locus; + +public: + std::string as_string () const override; + + ReferencePattern (std::unique_ptr 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 outer_attrs; + + // should this store location data? + +public: + StructPatternEtc (std::vector outer_attribs) + : outer_attrs (std::move (outer_attribs)) + {} + + // Creates an empty StructPatternEtc + static StructPatternEtc create_empty () + { + return StructPatternEtc (std::vector ()); + } +}; + +// Base class for a single field in a struct pattern - abstract +class StructPatternField +{ + std::vector outer_attrs; + Location locus; + +public: + virtual ~StructPatternField () {} + + // Unique pointer custom clone function + std::unique_ptr clone_struct_pattern_field () const + { + return std::unique_ptr ( + 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 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 tuple_pattern; + +public: + StructPatternFieldTuplePat (TupleIndex index, + std::unique_ptr tuple_pattern, + std::vector 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 ident_pattern; + +public: + StructPatternFieldIdentPat (Identifier ident, + std::unique_ptr ident_pattern, + std::vector 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 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 > 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 > 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 > 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::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 clone_tuple_struct_items () const + { + return std::unique_ptr (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 > patterns; + +public: + TupleStructItemsNoRange (std::vector > 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 > lower_patterns; + std::vector > upper_patterns; + +public: + TupleStructItemsRange (std::vector > lower_patterns, + std::vector > 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 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 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 clone_tuple_pattern_items () const + { + return std::unique_ptr ( + 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; + + 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 > patterns; + +public: + TuplePatternItemsMultiple (std::vector > 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 > lower_patterns; + std::vector > upper_patterns; + +public: + TuplePatternItemsRanged ( + std::vector > lower_patterns, + std::vector > 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 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 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_in_parens; + Location locus; + +public: + std::string as_string () const override + { + return "(" + pattern_in_parens->as_string () + ")"; + } + + GroupedPattern (std::unique_ptr 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 > items; + Location locus; + +public: + std::string as_string () const override; + + SlicePattern (std::vector > 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..61d9dcb --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -0,0 +1,232 @@ +// 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 +// . + +#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 outer_attrs; + + std::unique_ptr variables_pattern; + + // bool has_type; + std::unique_ptr type; + + // bool has_init_expr; + std::unique_ptr 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 variables_pattern, + std::unique_ptr init_expr, std::unique_ptr type, + std::vector 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; + +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; + +public: + std::string as_string () const override; + + ExprStmtWithoutBlock (Analysis::NodeMapping mappings, + std::unique_ptr 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; + +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 expr; + + std::string as_string () const override; + + std::vector locals; + + ExprStmtWithBlock (Analysis::NodeMapping mappings, + std::unique_ptr 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..0a446bd --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -0,0 +1,864 @@ +// 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 +// . + +#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 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 for_lifetimes + = std::vector ()) + : 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 > 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 ( + std::vector > type_param_bounds, + Location locus) + : type_param_bounds (std::move (type_param_bounds)), locus (locus) + {} + + // copy constructor with vector clone + ImplTraitType (ImplTraitType const &other) : locus (other.locus) + { + 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; + + 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 > + 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 ( + std::vector > type_param_bounds, + Location locus, bool is_dyn_dispatch = false) + : has_dyn (is_dyn_dispatch), + type_param_bounds (std::move (type_param_bounds)), locus (locus) + {} + + // copy constructor with vector clone + TraitObjectType (TraitObjectType const &other) + : has_dyn (other.has_dyn), locus (other.locus) + { + type_param_bounds.reserve (other.type_param_bounds.size ()); + for (const auto &e : other.type_param_bounds) + type_param_bounds.push_back (e->clone_type_param_bound ()); + } + + // overloaded assignment operator to clone + TraitObjectType &operator= (TraitObjectType const &other) + { + has_dyn = other.has_dyn; + locus = other.locus; + 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_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 (std::unique_ptr type_inside_parens, Location locus) + : type_in_parens (std::move (type_inside_parens)), locus (locus) + {} + + /* Copy constructor uses custom deep copy method for type to preserve + * polymorphism */ + ParenthesisedType (ParenthesisedType const &other) + : type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus) + {} + + // overload assignment operator to use custom clone method + ParenthesisedType &operator= (ParenthesisedType const &other) + { + type_in_parens = other.type_in_parens->clone_type (); + locus = other.locus; + return *this; + } + + // default move semantics + ParenthesisedType (ParenthesisedType &&other) = default; + ParenthesisedType &operator= (ParenthesisedType &&other) = default; + + std::string as_string () const 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 (TraitBound trait_bound, Location locus) + : 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 (TraitBound trait_bound, Location locus, + bool is_dyn_dispatch = false) + : has_dyn (is_dyn_dispatch), trait_bound (std::move (trait_bound)), + locus (locus) + {} + + std::string as_string () const 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 > 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 (std::vector > elems, Location locus) + : elems (std::move (elems)), locus (locus) + {} + + // copy constructor with vector clone + TupleType (TupleType const &other) : locus (other.locus) + { + 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 (Location locus) : 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 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 (PointerType pointer_type, + std::unique_ptr type_no_bounds, Location locus) + : pointer_type (pointer_type), type (std::move (type_no_bounds)), + locus (locus) + {} + + // Copy constructor calls custom polymorphic clone function + RawPointerType (RawPointerType const &other) + : pointer_type (other.pointer_type), + type (other.type->clone_type_no_bounds ()), locus (other.locus) + {} + + // overload assignment operator to use custom clone method + RawPointerType &operator= (RawPointerType const &other) + { + pointer_type = other.pointer_type; + type = other.type->clone_type_no_bounds (); + locus = other.locus; + return *this; + } + + // default move semantics + RawPointerType (RawPointerType &&other) = default; + RawPointerType &operator= (RawPointerType &&other) = default; + + std::string as_string () const 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 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 (bool is_mut, std::unique_ptr type_no_bounds, + Location locus, Lifetime lifetime = Lifetime::error ()) + : lifetime (std::move (lifetime)), has_mut (is_mut), + type (std::move (type_no_bounds)), locus (locus) + {} + + // Copy constructor with custom clone method + ReferenceType (ReferenceType const &other) + : lifetime (other.lifetime), has_mut (other.has_mut), + type (other.type->clone_type_no_bounds ()), locus (other.locus) + {} + + // Operator overload assignment operator to custom clone the unique pointer + ReferenceType &operator= (ReferenceType const &other) + { + lifetime = other.lifetime; + has_mut = other.has_mut; + type = other.type->clone_type_no_bounds (); + locus = other.locus; + + return *this; + } + + // move constructors + ReferenceType (ReferenceType &&other) = default; + ReferenceType &operator= (ReferenceType &&other) = default; + + std::string as_string () const 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 elem_type; + std::unique_ptr size; + Location locus; + +public: + // Constructor requires pointers for polymorphism + ArrayType (std::unique_ptr type, std::unique_ptr array_size, + Location locus) + : elem_type (std::move (type)), size (std::move (array_size)), locus (locus) + {} + + // Copy constructor requires deep copies of both unique pointers + ArrayType (ArrayType const &other) + : elem_type (other.elem_type->clone_type ()), + size (other.size->clone_expr ()), locus (other.locus) + {} + + // Overload assignment operator to deep copy pointers + ArrayType &operator= (ArrayType const &other) + { + elem_type = other.elem_type->clone_type (); + size = other.size->clone_expr (); + locus = other.locus; + return *this; + } + + // move constructors + ArrayType (ArrayType &&other) = default; + ArrayType &operator= (ArrayType &&other) = default; + + std::string as_string () const 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 elem_type; + Location locus; + +public: + // Constructor requires pointer for polymorphism + SliceType (std::unique_ptr type, Location locus) + : elem_type (std::move (type)), locus (locus) + {} + + // Copy constructor requires deep copy of Type smart pointer + SliceType (SliceType const &other) + : elem_type (other.elem_type->clone_type ()), locus (other.locus) + {} + + // Overload assignment operator to deep copy + SliceType &operator= (SliceType const &other) + { + elem_type = other.elem_type->clone_type (); + locus = other.locus; + + return *this; + } + + // move constructors + SliceType (SliceType &&other) = default; + SliceType &operator= (SliceType &&other) = default; + + std::string as_string () const 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 (Location locus) : 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 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 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 for_lifetimes; // inlined version + + FunctionQualifiers function_qualifiers; + std::vector params; + bool is_variadic; + + // bool has_return_type; + // BareFunctionReturnType return_type; + std::unique_ptr 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 (std::vector lifetime_params, + FunctionQualifiers qualifiers, + std::vector named_params, bool is_variadic, + std::unique_ptr type, Location locus) + : for_lifetimes (std::move (lifetime_params)), + function_qualifiers (std::move (qualifiers)), + params (std::move (named_params)), is_variadic (is_variadic), + return_type (std::move (type)), locus (locus) + {} + + // Copy constructor with clone + BareFunctionType (BareFunctionType const &other) + : for_lifetimes (other.for_lifetimes), + function_qualifiers (other.function_qualifiers), params (other.params), + is_variadic (other.is_variadic), + return_type (other.return_type->clone_type_no_bounds ()), + locus (other.locus) + {} + + // Overload assignment operator to deep copy + BareFunctionType &operator= (BareFunctionType const &other) + { + for_lifetimes = other.for_lifetimes; + function_qualifiers = other.function_qualifiers; + params = other.params; + is_variadic = other.is_variadic; + return_type = other.return_type->clone_type_no_bounds (); + locus = other.locus; + + return *this; + } + + // move constructors + BareFunctionType (BareFunctionType &&other) = default; + BareFunctionType &operator= (BareFunctionType &&other) = default; + + std::string as_string () const 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 +// . + +#ifndef RUST_HIR_VISITOR_H +#define RUST_HIR_VISITOR_H +// Visitor base for HIR + +// full include not required - only forward decls +#include "rust-hir-full-decls.h" + +namespace Rust { +namespace HIR { +/* Pure abstract class that provides an interface for accessing different + * classes of the HIR. */ +class HIRVisitor +{ +public: + // only concrete class overloads are required + + // rust-ast.h + // virtual void visit(AttrInput& attr_input) = 0; + // virtual void visit(TokenTree& token_tree) = 0; + // virtual void visit(MacroMatch& macro_match) = 0; + virtual void visit (Token &tok) = 0; + virtual void visit (DelimTokenTree &delim_tok_tree) = 0; + virtual void visit (AttrInputMetaItemContainer &input) = 0; + // virtual void visit(MetaItem& meta_item) = 0; + // virtual void visit(Stmt& stmt) = 0; + // virtual void visit(Expr& expr) = 0; + virtual void visit (IdentifierExpr &ident_expr) = 0; + // virtual void visit(Pattern& pattern) = 0; + // virtual void visit(Type& type) = 0; + // virtual void visit(TypeParamBound& type_param_bound) = 0; + virtual void visit (Lifetime &lifetime) = 0; + // virtual void visit(GenericParam& generic_param) = 0; + virtual void visit (LifetimeParam &lifetime_param) = 0; + // virtual void visit(TraitItem& trait_item) = 0; + // virtual void visit(InherentImplItem& inherent_impl_item) = 0; + // virtual void visit(TraitImplItem& trait_impl_item) = 0; + virtual void visit (MacroInvocationSemi ¯o) = 0; + + // rust-path.h + virtual void visit (PathInExpression &path) = 0; + virtual void visit (TypePathSegment &segment) = 0; + virtual void visit (TypePathSegmentGeneric &segment) = 0; + virtual void visit (TypePathSegmentFunction &segment) = 0; + virtual void visit (TypePath &path) = 0; + virtual void visit (QualifiedPathInExpression &path) = 0; + virtual void visit (QualifiedPathInType &path) = 0; + + // rust-expr.h + virtual void visit (LiteralExpr &expr) = 0; + virtual void visit (AttrInputLiteral &attr_input) = 0; + virtual void visit (MetaItemLitExpr &meta_item) = 0; + virtual void visit (MetaItemPathLit &meta_item) = 0; + virtual void visit (BorrowExpr &expr) = 0; + virtual void visit (DereferenceExpr &expr) = 0; + virtual void visit (ErrorPropagationExpr &expr) = 0; + virtual void visit (NegationExpr &expr) = 0; + virtual void visit (ArithmeticOrLogicalExpr &expr) = 0; + virtual void visit (ComparisonExpr &expr) = 0; + virtual void visit (LazyBooleanExpr &expr) = 0; + virtual void visit (TypeCastExpr &expr) = 0; + virtual void visit (AssignmentExpr &expr) = 0; + virtual void visit (CompoundAssignmentExpr &expr) = 0; + virtual void visit (GroupedExpr &expr) = 0; + // virtual void visit(ArrayElems& elems) = 0; + virtual void visit (ArrayElemsValues &elems) = 0; + virtual void visit (ArrayElemsCopied &elems) = 0; + virtual void visit (ArrayExpr &expr) = 0; + virtual void visit (ArrayIndexExpr &expr) = 0; + virtual void visit (TupleExpr &expr) = 0; + virtual void visit (TupleIndexExpr &expr) = 0; + virtual void visit (StructExprStruct &expr) = 0; + // virtual void visit(StructExprField& field) = 0; + virtual void visit (StructExprFieldIdentifier &field) = 0; + virtual void visit (StructExprFieldIdentifierValue &field) = 0; + virtual void visit (StructExprFieldIndexValue &field) = 0; + virtual void visit (StructExprStructFields &expr) = 0; + virtual void visit (StructExprStructBase &expr) = 0; + virtual void visit (StructExprTuple &expr) = 0; + virtual void visit (StructExprUnit &expr) = 0; + // virtual void visit(EnumExprField& field) = 0; + virtual void visit (EnumExprFieldIdentifier &field) = 0; + virtual void visit (EnumExprFieldIdentifierValue &field) = 0; + virtual void visit (EnumExprFieldIndexValue &field) = 0; + virtual void visit (EnumExprStruct &expr) = 0; + virtual void visit (EnumExprTuple &expr) = 0; + virtual void visit (EnumExprFieldless &expr) = 0; + virtual void visit (CallExpr &expr) = 0; + virtual void visit (MethodCallExpr &expr) = 0; + virtual void visit (FieldAccessExpr &expr) = 0; + virtual void visit (ClosureExprInner &expr) = 0; + virtual void visit (BlockExpr &expr) = 0; + virtual void visit (ClosureExprInnerTyped &expr) = 0; + virtual void visit (ContinueExpr &expr) = 0; + virtual void visit (BreakExpr &expr) = 0; + virtual void visit (RangeFromToExpr &expr) = 0; + virtual void visit (RangeFromExpr &expr) = 0; + virtual void visit (RangeToExpr &expr) = 0; + virtual void visit (RangeFullExpr &expr) = 0; + virtual void visit (RangeFromToInclExpr &expr) = 0; + virtual void visit (RangeToInclExpr &expr) = 0; + virtual void visit (ReturnExpr &expr) = 0; + virtual void visit (UnsafeBlockExpr &expr) = 0; + virtual void visit (LoopExpr &expr) = 0; + virtual void visit (WhileLoopExpr &expr) = 0; + virtual void visit (WhileLetLoopExpr &expr) = 0; + virtual void visit (ForLoopExpr &expr) = 0; + virtual void visit (IfExpr &expr) = 0; + virtual void visit (IfExprConseqElse &expr) = 0; + virtual void visit (IfExprConseqIf &expr) = 0; + virtual void visit (IfExprConseqIfLet &expr) = 0; + virtual void visit (IfLetExpr &expr) = 0; + virtual void visit (IfLetExprConseqElse &expr) = 0; + virtual void visit (IfLetExprConseqIf &expr) = 0; + virtual void visit (IfLetExprConseqIfLet &expr) = 0; + // virtual void visit(MatchCase& match_case) = 0; + // virtual void visit (MatchCaseBlockExpr &match_case) = 0; + // virtual void visit (MatchCaseExpr &match_case) = 0; + virtual void visit (MatchExpr &expr) = 0; + virtual void visit (AwaitExpr &expr) = 0; + virtual void visit (AsyncBlockExpr &expr) = 0; + + // rust-item.h + virtual void visit (TypeParam ¶m) = 0; + // virtual void visit(WhereClauseItem& item) = 0; + virtual void visit (LifetimeWhereClauseItem &item) = 0; + virtual void visit (TypeBoundWhereClauseItem &item) = 0; + virtual void visit (Method &method) = 0; + virtual void visit (ModuleBodied &module) = 0; + virtual void visit (ModuleNoBody &module) = 0; + virtual void visit (ExternCrate &crate) = 0; + // virtual void visit(UseTree& use_tree) = 0; + virtual void visit (UseTreeGlob &use_tree) = 0; + virtual void visit (UseTreeList &use_tree) = 0; + virtual void visit (UseTreeRebind &use_tree) = 0; + virtual void visit (UseDeclaration &use_decl) = 0; + virtual void visit (Function &function) = 0; + virtual void visit (TypeAlias &type_alias) = 0; + virtual void visit (StructStruct &struct_item) = 0; + virtual void visit (TupleStruct &tuple_struct) = 0; + virtual void visit (EnumItem &item) = 0; + virtual void visit (EnumItemTuple &item) = 0; + virtual void visit (EnumItemStruct &item) = 0; + virtual void visit (EnumItemDiscriminant &item) = 0; + virtual void visit (Enum &enum_item) = 0; + virtual void visit (Union &union_item) = 0; + virtual void visit (ConstantItem &const_item) = 0; + virtual void visit (StaticItem &static_item) = 0; + virtual void visit (TraitItemFunc &item) = 0; + virtual void visit (TraitItemMethod &item) = 0; + virtual void visit (TraitItemConst &item) = 0; + virtual void visit (TraitItemType &item) = 0; + virtual void visit (Trait &trait) = 0; + virtual void visit (InherentImpl &impl) = 0; + virtual void visit (TraitImpl &impl) = 0; + // virtual void visit(ExternalItem& item) = 0; + virtual void visit (ExternalStaticItem &item) = 0; + virtual void visit (ExternalFunctionItem &item) = 0; + virtual void visit (ExternBlock &block) = 0; + + // rust-macro.h + virtual void visit (MacroMatchFragment &match) = 0; + virtual void visit (MacroMatchRepetition &match) = 0; + virtual void visit (MacroMatcher &matcher) = 0; + virtual void visit (MacroRulesDefinition &rules_def) = 0; + virtual void visit (MacroInvocation ¯o_invoc) = 0; + virtual void visit (MetaItemPath &meta_item) = 0; + virtual void visit (MetaItemSeq &meta_item) = 0; + virtual void visit (MetaWord &meta_item) = 0; + virtual void visit (MetaNameValueStr &meta_item) = 0; + virtual void visit (MetaListPaths &meta_item) = 0; + virtual void visit (MetaListNameValueStr &meta_item) = 0; + + // rust-pattern.h + virtual void visit (LiteralPattern &pattern) = 0; + virtual void visit (IdentifierPattern &pattern) = 0; + virtual void visit (WildcardPattern &pattern) = 0; + // virtual void visit(RangePatternBound& bound) = 0; + virtual void visit (RangePatternBoundLiteral &bound) = 0; + virtual void visit (RangePatternBoundPath &bound) = 0; + virtual void visit (RangePatternBoundQualPath &bound) = 0; + virtual void visit (RangePattern &pattern) = 0; + virtual void visit (ReferencePattern &pattern) = 0; + // virtual void visit(StructPatternField& field) = 0; + virtual void visit (StructPatternFieldTuplePat &field) = 0; + virtual void visit (StructPatternFieldIdentPat &field) = 0; + virtual void visit (StructPatternFieldIdent &field) = 0; + virtual void visit (StructPattern &pattern) = 0; + // virtual void visit(TupleStructItems& tuple_items) = 0; + virtual void visit (TupleStructItemsNoRange &tuple_items) = 0; + virtual void visit (TupleStructItemsRange &tuple_items) = 0; + virtual void visit (TupleStructPattern &pattern) = 0; + // virtual void visit(TuplePatternItems& tuple_items) = 0; + virtual void visit (TuplePatternItemsMultiple &tuple_items) = 0; + virtual void visit (TuplePatternItemsRanged &tuple_items) = 0; + virtual void visit (TuplePattern &pattern) = 0; + virtual void visit (GroupedPattern &pattern) = 0; + virtual void visit (SlicePattern &pattern) = 0; + + // rust-stmt.h + virtual void visit (EmptyStmt &stmt) = 0; + virtual void visit (LetStmt &stmt) = 0; + virtual void visit (ExprStmtWithoutBlock &stmt) = 0; + virtual void visit (ExprStmtWithBlock &stmt) = 0; + + // rust-type.h + virtual void visit (TraitBound &bound) = 0; + virtual void visit (ImplTraitType &type) = 0; + virtual void visit (TraitObjectType &type) = 0; + virtual void visit (ParenthesisedType &type) = 0; + virtual void visit (ImplTraitTypeOneBound &type) = 0; + virtual void visit (TraitObjectTypeOneBound &type) = 0; + virtual void visit (TupleType &type) = 0; + virtual void visit (NeverType &type) = 0; + virtual void visit (RawPointerType &type) = 0; + virtual void visit (ReferenceType &type) = 0; + virtual void visit (ArrayType &type) = 0; + virtual void visit (SliceType &type) = 0; + virtual void visit (InferredType &type) = 0; + virtual void visit (BareFunctionType &type) = 0; + + // TODO: rust-cond-compilation.h visiting? not currently used +}; +} // namespace HIR +} // namespace Rust + +#endif diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h new file mode 100644 index 0000000..b7feb59 --- /dev/null +++ b/gcc/rust/hir/tree/rust-hir.h @@ -0,0 +1,1459 @@ +// 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 +// . + +#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 clone_attr_input () const + { + return std::unique_ptr (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 clone_token_tree () const + { + return std::unique_ptr (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 > 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 clone_macro_match () const + { + return std::unique_ptr (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 clone_token () const + { + return std::unique_ptr (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 > 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 > 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 > token_trees + = std::vector > (), + 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 > to_token_stream () const override; + + std::unique_ptr clone_delim_token_tree () const + { + return std::unique_ptr (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 segments; + Location locus; + +public: + // Constructor + SimplePath (std::vector 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 ()); + } + + // 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 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 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 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 clone_attribute () const + { + return std::unique_ptr (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 clone_meta_item_inner () const + { + return std::unique_ptr (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 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 > items; + +public: + AttrInputMetaItemContainer ( + std::vector > 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 + clone_attr_input_meta_item_container () const + { + return std::unique_ptr ( + 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 clone_stmt () const + { + return std::unique_ptr (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 outer_attrs; + + // TODO: should outer attrs be defined here or in each derived class? + +public: + // Unique pointer custom clone function + std::unique_ptr clone_item () const + { + return std::unique_ptr (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 &names ATTRIBUTE_UNUSED) const + {} + + virtual void accept_vis (HIRVisitor &vis ATTRIBUTE_UNUSED) {} + +protected: + // Constructor + Item (Analysis::NodeMapping mappings, + std::vector outer_attribs = std::vector ()) + : 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 outer_attrs; + + Analysis::NodeMapping mappings; + +public: + const std::vector &get_outer_attrs () const { return outer_attrs; } + + // Unique pointer custom clone function + std::unique_ptr clone_expr () const + { + return std::unique_ptr (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 outer_attribs = std::vector ()) + : 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 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 outer_attribs + = std::vector ()) + : 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 clone_expr_without_block () const + { + return std::unique_ptr (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 outer_attrs + = std::vector ()) + : 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 clone_identifier_expr () const + { + return std::unique_ptr (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 clone_pattern () const + { + return std::unique_ptr (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 clone_type () const + { + return std::unique_ptr (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; + +protected: + // Clone function implementation as pure virtual method + virtual Type *clone_type_impl () const = 0; +}; + +// A type without parentheses? - abstract +class TypeNoBounds : public Type +{ +public: + // Unique pointer custom clone function + std::unique_ptr clone_type_no_bounds () const + { + return std::unique_ptr (clone_type_no_bounds_impl ()); + } + +protected: + // Clone function implementation as pure virtual method + virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0; + + /* Save having to specify two clone methods in derived classes by making type + * clone return typenobounds clone. Hopefully won't affect performance too + * much. */ + 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 clone_type_param_bound () const + { + return std::unique_ptr (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 clone_generic_param () const + { + return std::unique_ptr (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_bounds; // inlined LifetimeBounds + + // bool has_outer_attribute; + // std::unique_ptr 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_bounds + = std::vector (), + 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 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 outer_attrs; + + // NOTE: all children should have outer attributes + +protected: + // Constructor + /*TraitItem(std::vector outer_attrs = std::vector()) + : 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 clone_trait_item () const + { + return std::unique_ptr (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 clone_inherent_impl_item () const + { + return std::unique_ptr (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 clone_trait_impl_item () const + { + return std::unique_ptr (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 > token_trees; + Location locus; + +public: + std::string as_string () const override; + + MacroInvocationSemi (Analysis::NodeMapping mappings, SimplePath macro_path, + DelimType delim_type, + std::vector > token_trees, + std::vector 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 clone_macro_invocation_semi () const + { + return std::unique_ptr ( + 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 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 > items; + + Analysis::NodeMapping mappings; + +public: + // Constructor + Crate (std::vector > items, + std::vector 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 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 outer_attrs) + { + set_outer_attrs (std::move (outer_attrs)); + } +}; +} // namespace HIR +} // namespace Rust + +#endif -- cgit v1.1 From 2cfc6276dadc54aea9f8ce2a8cfefaee456f380e Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 10 Dec 2020 17:59:21 +0000 Subject: Add AST->HIR lowering pass This is the initial pass to move the AST to HIR. It is very extensible and easy to maintain now. --- gcc/rust/Make-lang.in | 9 +- gcc/rust/hir/README.md | 40 ++++++ gcc/rust/hir/rust-ast-lower-base.h | 251 ++++++++++++++++++++++++++++++++++ gcc/rust/hir/rust-ast-lower-expr.h | 240 ++++++++++++++++++++++++++++++++ gcc/rust/hir/rust-ast-lower-item.h | 134 ++++++++++++++++++ gcc/rust/hir/rust-ast-lower-pattern.h | 58 ++++++++ gcc/rust/hir/rust-ast-lower-stmt.h | 96 +++++++++++++ gcc/rust/hir/rust-ast-lower-type.h | 84 ++++++++++++ gcc/rust/hir/rust-ast-lower.cc | 62 +++++++++ gcc/rust/hir/rust-ast-lower.h | 46 +++++++ gcc/rust/rust-session-manager.cc | 37 ++++- 11 files changed, 1052 insertions(+), 5 deletions(-) create mode 100644 gcc/rust/hir/README.md create mode 100644 gcc/rust/hir/rust-ast-lower-base.h create mode 100644 gcc/rust/hir/rust-ast-lower-expr.h create mode 100644 gcc/rust/hir/rust-ast-lower-item.h create mode 100644 gcc/rust/hir/rust-ast-lower-pattern.h create mode 100644 gcc/rust/hir/rust-ast-lower-stmt.h create mode 100644 gcc/rust/hir/rust-ast-lower-type.h create mode 100644 gcc/rust/hir/rust-ast-lower.cc create mode 100644 gcc/rust/hir/rust-ast-lower.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index dd42b1d..b9b2345 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -74,8 +74,9 @@ GRS_OBJS = \ rust/rust-scan.o \ rust/rust-compile.o \ rust/rust-macro-expand.o \ - rust/rust-hir-map.o \ rust/rust-hir-full-test.o \ + rust/rust-hir-map.o \ + rust/rust-ast-lower.o \ $(END) # removed object files from here @@ -275,8 +276,14 @@ 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) + 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 +// . + +#ifndef RUST_AST_LOWER_BASE +#define RUST_AST_LOWER_BASE + +#include "rust-system.h" +#include "rust-ast-full.h" +#include "rust-ast-visitor.h" +#include "rust-hir-map.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace HIR { + +// base class to allow derivatives to overload as needed +class ASTLoweringBase : public AST::ASTVisitor +{ +public: + virtual ~ASTLoweringBase () {} + + // visitor impl + // rust-ast.h + // virtual void visit(AttrInput& attr_input); + // virtual void visit(TokenTree& token_tree); + // virtual void visit(MacroMatch& macro_match); + virtual void visit (AST::Token &tok) {} + virtual void visit (AST::DelimTokenTree &delim_tok_tree) {} + virtual void visit (AST::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // void vsit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (AST::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (AST::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (AST::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (AST::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (AST::PathInExpression &path) {} + virtual void visit (AST::TypePathSegment &segment) {} + virtual void visit (AST::TypePathSegmentGeneric &segment) {} + virtual void visit (AST::TypePathSegmentFunction &segment) {} + virtual void visit (AST::TypePath &path) {} + virtual void visit (AST::QualifiedPathInExpression &path) {} + virtual void visit (AST::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (AST::LiteralExpr &expr) {} + virtual void visit (AST::AttrInputLiteral &attr_input) {} + virtual void visit (AST::MetaItemLitExpr &meta_item) {} + virtual void visit (AST::MetaItemPathLit &meta_item) {} + virtual void visit (AST::BorrowExpr &expr) {} + virtual void visit (AST::DereferenceExpr &expr) {} + virtual void visit (AST::ErrorPropagationExpr &expr) {} + virtual void visit (AST::NegationExpr &expr) {} + virtual void visit (AST::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (AST::ComparisonExpr &expr) {} + virtual void visit (AST::LazyBooleanExpr &expr) {} + virtual void visit (AST::TypeCastExpr &expr) {} + virtual void visit (AST::AssignmentExpr &expr) {} + virtual void visit (AST::CompoundAssignmentExpr &expr) {} + virtual void visit (AST::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (AST::ArrayElemsValues &elems) {} + virtual void visit (AST::ArrayElemsCopied &elems) {} + virtual void visit (AST::ArrayExpr &expr) {} + virtual void visit (AST::ArrayIndexExpr &expr) {} + virtual void visit (AST::TupleExpr &expr) {} + virtual void visit (AST::TupleIndexExpr &expr) {} + virtual void visit (AST::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (AST::StructExprFieldIdentifier &field) {} + virtual void visit (AST::StructExprFieldIdentifierValue &field) {} + virtual void visit (AST::StructExprFieldIndexValue &field) {} + virtual void visit (AST::StructExprStructFields &expr) {} + virtual void visit (AST::StructExprStructBase &expr) {} + virtual void visit (AST::StructExprTuple &expr) {} + virtual void visit (AST::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (AST::EnumExprFieldIdentifier &field) {} + virtual void visit (AST::EnumExprFieldIdentifierValue &field) {} + virtual void visit (AST::EnumExprFieldIndexValue &field) {} + virtual void visit (AST::EnumExprStruct &expr) {} + virtual void visit (AST::EnumExprTuple &expr) {} + virtual void visit (AST::EnumExprFieldless &expr) {} + virtual void visit (AST::CallExpr &expr) {} + virtual void visit (AST::MethodCallExpr &expr) {} + virtual void visit (AST::FieldAccessExpr &expr) {} + virtual void visit (AST::ClosureExprInner &expr) {} + virtual void visit (AST::BlockExpr &expr) {} + virtual void visit (AST::ClosureExprInnerTyped &expr) {} + virtual void visit (AST::ContinueExpr &expr) {} + virtual void visit (AST::BreakExpr &expr) {} + virtual void visit (AST::RangeFromToExpr &expr) {} + virtual void visit (AST::RangeFromExpr &expr) {} + virtual void visit (AST::RangeToExpr &expr) {} + virtual void visit (AST::RangeFullExpr &expr) {} + virtual void visit (AST::RangeFromToInclExpr &expr) {} + virtual void visit (AST::RangeToInclExpr &expr) {} + virtual void visit (AST::ReturnExpr &expr) {} + virtual void visit (AST::UnsafeBlockExpr &expr) {} + virtual void visit (AST::LoopExpr &expr) {} + virtual void visit (AST::WhileLoopExpr &expr) {} + virtual void visit (AST::WhileLetLoopExpr &expr) {} + virtual void visit (AST::ForLoopExpr &expr) {} + virtual void visit (AST::IfExpr &expr) {} + virtual void visit (AST::IfExprConseqElse &expr) {} + virtual void visit (AST::IfExprConseqIf &expr) {} + virtual void visit (AST::IfExprConseqIfLet &expr) {} + virtual void visit (AST::IfLetExpr &expr) {} + virtual void visit (AST::IfLetExprConseqElse &expr) {} + virtual void visit (AST::IfLetExprConseqIf &expr) {} + virtual void visit (AST::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (AST::MatchCaseBlockExpr &match_case) {} + // virtual void visit (AST::MatchCaseExpr &match_case) {} + virtual void visit (AST::MatchExpr &expr) {} + virtual void visit (AST::AwaitExpr &expr) {} + virtual void visit (AST::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (AST::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (AST::LifetimeWhereClauseItem &item) {} + virtual void visit (AST::TypeBoundWhereClauseItem &item) {} + virtual void visit (AST::Method &method) {} + virtual void visit (AST::ModuleBodied &module) {} + virtual void visit (AST::ModuleNoBody &module) {} + virtual void visit (AST::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (AST::UseTreeGlob &use_tree) {} + virtual void visit (AST::UseTreeList &use_tree) {} + virtual void visit (AST::UseTreeRebind &use_tree) {} + virtual void visit (AST::UseDeclaration &use_decl) {} + virtual void visit (AST::Function &function) {} + virtual void visit (AST::TypeAlias &type_alias) {} + virtual void visit (AST::StructStruct &struct_item) {} + virtual void visit (AST::TupleStruct &tuple_struct) {} + virtual void visit (AST::EnumItem &item) {} + virtual void visit (AST::EnumItemTuple &item) {} + virtual void visit (AST::EnumItemStruct &item) {} + virtual void visit (AST::EnumItemDiscriminant &item) {} + virtual void visit (AST::Enum &enum_item) {} + virtual void visit (AST::Union &union_item) {} + virtual void visit (AST::ConstantItem &const_item) {} + virtual void visit (AST::StaticItem &static_item) {} + virtual void visit (AST::TraitItemFunc &item) {} + virtual void visit (AST::TraitItemMethod &item) {} + virtual void visit (AST::TraitItemConst &item) {} + virtual void visit (AST::TraitItemType &item) {} + virtual void visit (AST::Trait &trait) {} + virtual void visit (AST::InherentImpl &impl) {} + virtual void visit (AST::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (AST::ExternalStaticItem &item) {} + virtual void visit (AST::ExternalFunctionItem &item) {} + virtual void visit (AST::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (AST::MacroMatchFragment &match) {} + virtual void visit (AST::MacroMatchRepetition &match) {} + virtual void visit (AST::MacroMatcher &matcher) {} + virtual void visit (AST::MacroRulesDefinition &rules_def) {} + virtual void visit (AST::MacroInvocation ¯o_invoc) {} + virtual void visit (AST::MetaItemPath &meta_item) {} + virtual void visit (AST::MetaItemSeq &meta_item) {} + virtual void visit (AST::MetaWord &meta_item) {} + virtual void visit (AST::MetaNameValueStr &meta_item) {} + virtual void visit (AST::MetaListPaths &meta_item) {} + virtual void visit (AST::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (AST::LiteralPattern &pattern) {} + virtual void visit (AST::IdentifierPattern &pattern) {} + virtual void visit (AST::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (AST::RangePatternBoundLiteral &bound) {} + virtual void visit (AST::RangePatternBoundPath &bound) {} + virtual void visit (AST::RangePatternBoundQualPath &bound) {} + virtual void visit (AST::RangePattern &pattern) {} + virtual void visit (AST::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (AST::StructPatternFieldTuplePat &field) {} + virtual void visit (AST::StructPatternFieldIdentPat &field) {} + virtual void visit (AST::StructPatternFieldIdent &field) {} + virtual void visit (AST::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (AST::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (AST::TupleStructItemsRange &tuple_items) {} + virtual void visit (AST::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (AST::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (AST::TuplePattern &pattern) {} + virtual void visit (AST::GroupedPattern &pattern) {} + virtual void visit (AST::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (AST::EmptyStmt &stmt) {} + virtual void visit (AST::LetStmt &stmt) {} + virtual void visit (AST::ExprStmtWithoutBlock &stmt) {} + virtual void visit (AST::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (AST::TraitBound &bound) {} + virtual void visit (AST::ImplTraitType &type) {} + virtual void visit (AST::TraitObjectType &type) {} + virtual void visit (AST::ParenthesisedType &type) {} + virtual void visit (AST::ImplTraitTypeOneBound &type) {} + virtual void visit (AST::TraitObjectTypeOneBound &type) {} + virtual void visit (AST::TupleType &type) {} + virtual void visit (AST::NeverType &type) {} + virtual void visit (AST::RawPointerType &type) {} + virtual void visit (AST::ReferenceType &type) {} + virtual void visit (AST::ArrayType &type) {} + virtual void visit (AST::SliceType &type) {} + virtual void visit (AST::InferredType &type) {} + virtual void visit (AST::BareFunctionType &type) {} + +protected: + ASTLoweringBase () : mappings (Analysis::Mappings::get ()) {} + + Analysis::Mappings *mappings; +}; + +} // namespace HIR +} // namespace Rust + +#endif // RUST_AST_LOWER_BASE diff --git a/gcc/rust/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h new file mode 100644 index 0000000..6454a78 --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-expr.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 +// . + +#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 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_return_expr () + ? ASTLoweringExpr::translate (expr.get_expr ()) + : 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 (return_expr)); + } + + void visit (AST::CallExpr &expr) + { + std::vector outer_attribs; + HIR::Expr *func = ASTLoweringExpr::translate (expr.function.get ()); + std::vector > params; + expr.iterate_params ([&] (AST::Expr *p) mutable -> bool { + auto trans = ASTLoweringExpr::translate (p); + params.push_back (std::unique_ptr (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 (func), + std::move (params), std::move (outer_attribs), + expr.get_locus ()); + } + + void visit (AST::AssignmentExpr &expr) + { + HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_lhs ()); + HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_rhs ()); + + 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 (lhs), + std::unique_ptr (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_lhs ()); + rust_assert (lhs != nullptr); + HIR::Expr *rhs = ASTLoweringExpr::translate (expr.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 (lhs), + std::unique_ptr (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..5983e88 --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -0,0 +1,134 @@ +// 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 +// . + +#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 > generic_params; + std::vector outer_attrs; + std::vector > 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.function_name; + Location locus = function.get_locus (); + + std::unique_ptr return_type + = function.has_function_return_type () ? std::unique_ptr ( + ASTLoweringType::translate (function.return_type.get ())) + : nullptr; + + std::vector function_params; + for (auto ¶m : function.function_params) + { + auto translated_pattern = std::unique_ptr ( + ASTLoweringPattern::translate (param.param_name.get ())); + auto translated_type = std::unique_ptr ( + ASTLoweringType::translate (param.type.get ())); + + function_params.push_back ( + HIR::FunctionParam (std::move (translated_pattern), + std::move (translated_type), param.get_locus ())); + } + + std::unique_ptr function_body + = std::unique_ptr ( + translate (function.function_body.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)); + + translated + = 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 (), + translated); + } + + // Helpers + + HIR::BlockExpr *translate (AST::BlockExpr *function_body) + { + std::vector > block_stmts; + std::unique_ptr block_expr; + std::vector inner_attribs; + std::vector outer_attribs; + + function_body->iterate_stmts ([&] (AST::Stmt *s) mutable -> bool { + auto translated_stmt = ASTLoweringStmt::translate (s); + block_stmts.push_back (std::unique_ptr (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..b69c9d9 --- /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 +// . + +#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 to_bind; + translated + = new HIR::IdentifierPattern (pattern.variable_ident, + pattern.get_locus (), pattern.is_ref, + pattern.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..d21b49d --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -0,0 +1,96 @@ +// 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 +// . + +#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.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 (expr), + stmt.get_locus ()); + } + + void visit (AST::LetStmt &stmt) + { + std::vector outer_attrs; + HIR::Pattern *variables + = ASTLoweringPattern::translate (stmt.variables_pattern.get ()); + HIR::Type *type = stmt.has_type () + ? ASTLoweringType::translate (stmt.type.get ()) + : nullptr; + HIR::Expr *init_expression + = stmt.has_init_expr () + ? ASTLoweringExpr::translate (stmt.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 (variables), + std::unique_ptr (init_expression), + std::unique_ptr (type), + std::move (outer_attrs), stmt.get_locus ()); + } + +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..9611ca0 --- /dev/null +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -0,0 +1,84 @@ +// 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 +// . + +#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 > 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 (translated_segment)); + return true; + }); + + translated + = new HIR::TypePath (std::move (translated_segments), path.get_locus (), + path.has_opening_scope_resolution_op ()); + } + +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 +// . + +#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 > items; + std::vector 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 (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 +// . + +#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/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index da50948..f526da1 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 +// . +// #include "rust-session-manager.h" + +#include "rust-session-manager.h" #include "rust-diagnostics.h" #include "diagnostic.h" #include "input.h" @@ -13,13 +31,13 @@ #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-compile.h" +// hir passes wip +#include "rust-ast-lower.h" #include "rust-target.h" -#include - extern Linemap * rust_get_linemap (); @@ -405,6 +423,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 +450,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) { @@ -740,6 +763,12 @@ Session::resolution (AST::Crate &crate) // Name resolution must be in front of type resolution Analysis::NameResolution::Resolve (crate, toplevel); Analysis::TypeResolution::Resolve (crate, toplevel); + + // inject hir passes + HIR::Crate hir = HIR::ASTLowering::Resolve (crate); + fprintf (stderr, "HIR PASSES:\n"); + fprintf (stderr, "%s", hir.as_string ().c_str ()); + fprintf (stderr, "HIR PASSES - DONE:\n"); fprintf (stderr, "finished name resolution\n"); } -- cgit v1.1 From 4fb0ab7e635c65318aadf958e0e1303f3435c4e5 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Thu, 10 Dec 2020 20:02:03 +0000 Subject: This sets up a name resolution framework trying to follow rust-dev guide We can use the NodeId from the AST to generate apropriate mappings for all names and types. Ribs are the scopes for names being instansiated, and reference to defintion tables allows all names to be resolved to NodeId's. Later on NodeIds will map over to HIR ids allowing for type resolution. --- gcc/rust/Make-lang.in | 7 +- gcc/rust/ast/rust-ast.h | 111 +++--------- gcc/rust/ast/rust-expr.h | 5 - gcc/rust/ast/rust-path.h | 10 +- gcc/rust/ast/rust-pattern.h | 12 +- gcc/rust/hir/rust-ast-lower-expr.h | 18 +- gcc/rust/hir/rust-ast-lower-item.h | 16 +- gcc/rust/hir/rust-ast-lower-pattern.h | 6 +- gcc/rust/hir/rust-ast-lower-stmt.h | 8 +- gcc/rust/resolve/rust-ast-resolve-base.h | 258 +++++++++++++++++++++++++++ gcc/rust/resolve/rust-ast-resolve-expr.h | 98 ++++++++++ gcc/rust/resolve/rust-ast-resolve-item.h | 68 +++++++ gcc/rust/resolve/rust-ast-resolve-pattern.h | 97 ++++++++++ gcc/rust/resolve/rust-ast-resolve-stmt.h | 59 ++++++ gcc/rust/resolve/rust-ast-resolve-toplevel.h | 54 ++++++ gcc/rust/resolve/rust-ast-resolve-type.h | 66 +++++++ gcc/rust/resolve/rust-ast-resolve.cc | 245 +++++++++++++++++++++++++ gcc/rust/resolve/rust-ast-resolve.h | 50 ++++++ gcc/rust/resolve/rust-name-resolver.h | 211 ++++++++++++++++++++++ gcc/rust/rust-session-manager.cc | 31 ++-- gcc/rust/rust-session-manager.h | 29 ++- gcc/rust/util/rust-hir-map.cc | 10 +- gcc/rust/util/rust-hir-map.h | 5 + 23 files changed, 1329 insertions(+), 145 deletions(-) create mode 100644 gcc/rust/resolve/rust-ast-resolve-base.h create mode 100644 gcc/rust/resolve/rust-ast-resolve-expr.h create mode 100644 gcc/rust/resolve/rust-ast-resolve-item.h create mode 100644 gcc/rust/resolve/rust-ast-resolve-pattern.h create mode 100644 gcc/rust/resolve/rust-ast-resolve-stmt.h create mode 100644 gcc/rust/resolve/rust-ast-resolve-toplevel.h create mode 100644 gcc/rust/resolve/rust-ast-resolve-type.h create mode 100644 gcc/rust/resolve/rust-ast-resolve.cc create mode 100644 gcc/rust/resolve/rust-ast-resolve.h create mode 100644 gcc/rust/resolve/rust-name-resolver.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index b9b2345..aa81813 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -77,6 +77,7 @@ GRS_OBJS = \ rust/rust-hir-full-test.o \ rust/rust-hir-map.o \ rust/rust-ast-lower.o \ + rust/rust-ast-resolve.o \ $(END) # removed object files from here @@ -229,7 +230,7 @@ RUST_INCLUDES = -I $(srcdir)/rust \ -I $(srcdir)/rust/expand \ -I $(srcdir)/rust/hir/tree \ -I $(srcdir)/rust/hir \ - -I $(srcdir)/rust/hir_resolve \ + -I $(srcdir)/rust/resolve \ -I $(srcdir)/rust/util # add files that require cross-folder includes - currently rust-lang.o, rust-lex.o @@ -286,4 +287,8 @@ rust/%.o: rust/hir/tree/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) +# build rust/hir/tree files in rust folder +rust/%.o: rust/resolve/%.cc + $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< + $(POSTCOMPILE) diff --git a/gcc/rust/ast/rust-ast.h b/gcc/rust/ast/rust-ast.h index fe60ae0..b26c770 100644 --- a/gcc/rust/ast/rust-ast.h +++ b/gcc/rust/ast/rust-ast.h @@ -266,91 +266,6 @@ public: bool is_error () const { return value_as_string == ""; } }; -// A token tree with delimiters -class DelimTokenTree : public TokenTree, public AttrInput -{ - DelimType delim_type; - std::vector > 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 > token_trees - = std::vector > (), - 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 (ASTVisitor &vis) override; - - bool - check_cfg_predicate (const Session &session ATTRIBUTE_UNUSED) const override - { - // this should never be called - should be converted first - return false; - } - - AttrInput *parse_to_meta_item () const override; - - std::vector > to_token_stream () const override; - - std::unique_ptr clone_delim_token_tree () const - { - return std::unique_ptr (clone_delim_tok_tree_impl ()); - } -}; - /* Forward decl - definition moved to rust-expr.h as it requires LiteralExpr to * be defined */ class AttrInputLiteral; @@ -955,7 +870,7 @@ public: virtual void mark_for_strip () = 0; virtual bool is_marked_for_strip () const = 0; - NodeId get_node_id () const { return node_id; } + virtual NodeId get_node_id () const { return node_id; } protected: // Constructor @@ -1090,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 @@ -1127,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 @@ -1153,6 +1080,8 @@ protected: { return clone_type_no_bounds_impl (); } + + TypeNoBounds () : Type () {} }; /* Abstract base class representing a type param bound - Lifetime and TraitBound @@ -1572,19 +1501,22 @@ struct Crate * top-level one)? */ std::vector > items; + NodeId node_id; + public: // Constructor Crate (std::vector > items, std::vector 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) @@ -1599,6 +1531,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) @@ -1624,6 +1557,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 864ee1d..de011c1 100644 --- a/gcc/rust/ast/rust-expr.h +++ b/gcc/rust/ast/rust-expr.h @@ -2338,11 +2338,6 @@ public: } } -protected: - /* Use covariance to implement clone function as returning this object rather - * than base */ - CallExpr *clone_expr_impl () const override { return new CallExpr (*this); } - // TODO: this mutable getter seems really dodgy. Think up better way. const std::vector > &get_params () const { diff --git a/gcc/rust/ast/rust-path.h b/gcc/rust/ast/rust-path.h index 20138b6..bd3b0f0 100644 --- a/gcc/rust/ast/rust-path.h +++ b/gcc/rust/ast/rust-path.h @@ -296,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; @@ -307,7 +309,8 @@ public: = std::vector ()) : 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. @@ -341,6 +344,8 @@ public: 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 * than base */ @@ -654,7 +659,8 @@ public: // Constructor TypePath (std::vector > 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) {} 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 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/hir/rust-ast-lower-expr.h b/gcc/rust/hir/rust-ast-lower-expr.h index 6454a78..50e67a8 100644 --- a/gcc/rust/hir/rust-ast-lower-expr.h +++ b/gcc/rust/hir/rust-ast-lower-expr.h @@ -70,9 +70,10 @@ public: void visit (AST::ReturnExpr &expr) { - HIR::Expr *return_expr = expr.has_return_expr () - ? ASTLoweringExpr::translate (expr.get_expr ()) - : nullptr; + 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 (), @@ -86,7 +87,8 @@ public: void visit (AST::CallExpr &expr) { std::vector outer_attribs; - HIR::Expr *func = ASTLoweringExpr::translate (expr.function.get ()); + HIR::Expr *func + = ASTLoweringExpr::translate (expr.get_function_expr ().get ()); std::vector > params; expr.iterate_params ([&] (AST::Expr *p) mutable -> bool { auto trans = ASTLoweringExpr::translate (p); @@ -107,8 +109,8 @@ public: void visit (AST::AssignmentExpr &expr) { - HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_lhs ()); - HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_rhs ()); + 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 (), @@ -211,9 +213,9 @@ public: break; } - HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_lhs ()); + HIR::Expr *lhs = ASTLoweringExpr::translate (expr.get_left_expr ().get ()); rust_assert (lhs != nullptr); - HIR::Expr *rhs = ASTLoweringExpr::translate (expr.right_expr.get ()); + HIR::Expr *rhs = ASTLoweringExpr::translate (expr.get_right_expr ().get ()); rust_assert (rhs != nullptr); auto crate_num = mappings->get_current_crate (); diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 5983e88..71e465e 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -53,21 +53,21 @@ public: HIR::Visibility vis = HIR::Visibility::create_public (); // need - Identifier function_name = function.function_name; + Identifier function_name = function.get_function_name (); Location locus = function.get_locus (); std::unique_ptr return_type - = function.has_function_return_type () ? std::unique_ptr ( - ASTLoweringType::translate (function.return_type.get ())) - : nullptr; + = function.has_return_type () ? std::unique_ptr ( + ASTLoweringType::translate (function.get_return_type ().get ())) + : nullptr; std::vector function_params; - for (auto ¶m : function.function_params) + for (auto ¶m : function.get_function_params ()) { auto translated_pattern = std::unique_ptr ( - ASTLoweringPattern::translate (param.param_name.get ())); + ASTLoweringPattern::translate (param.get_pattern ().get ())); auto translated_type = std::unique_ptr ( - ASTLoweringType::translate (param.type.get ())); + ASTLoweringType::translate (param.get_type ().get ())); function_params.push_back ( HIR::FunctionParam (std::move (translated_pattern), @@ -76,7 +76,7 @@ public: std::unique_ptr function_body = std::unique_ptr ( - translate (function.function_body.get ())); + translate (function.get_definition ().get ())); auto crate_num = mappings->get_current_crate (); Analysis::NodeMapping mapping (crate_num, function.get_node_id (), diff --git a/gcc/rust/hir/rust-ast-lower-pattern.h b/gcc/rust/hir/rust-ast-lower-pattern.h index b69c9d9..0d5ce0f 100644 --- a/gcc/rust/hir/rust-ast-lower-pattern.h +++ b/gcc/rust/hir/rust-ast-lower-pattern.h @@ -41,9 +41,9 @@ public: { std::unique_ptr to_bind; translated - = new HIR::IdentifierPattern (pattern.variable_ident, - pattern.get_locus (), pattern.is_ref, - pattern.is_mut, std::move (to_bind)); + = new HIR::IdentifierPattern (pattern.get_ident (), pattern.get_locus (), + pattern.get_is_ref (), + pattern.get_is_mut (), std::move (to_bind)); } private: diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h index d21b49d..d18dc19 100644 --- a/gcc/rust/hir/rust-ast-lower-stmt.h +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -48,7 +48,7 @@ public: void visit (AST::ExprStmtWithoutBlock &stmt) { - HIR::Expr *expr = ASTLoweringExpr::translate (stmt.expr.get ()); + 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 (), @@ -64,13 +64,13 @@ public: { std::vector outer_attrs; HIR::Pattern *variables - = ASTLoweringPattern::translate (stmt.variables_pattern.get ()); + = ASTLoweringPattern::translate (stmt.get_pattern ().get ()); HIR::Type *type = stmt.has_type () - ? ASTLoweringType::translate (stmt.type.get ()) + ? ASTLoweringType::translate (stmt.get_type ().get ()) : nullptr; HIR::Expr *init_expression = stmt.has_init_expr () - ? ASTLoweringExpr::translate (stmt.init_expr.get ()) + ? ASTLoweringExpr::translate (stmt.get_init_expr ().get ()) : nullptr; auto crate_num = mappings->get_current_crate (); 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 +// . + +#ifndef RUST_AST_RESOLVE_BASE_H +#define RUST_AST_RESOLVE_BASE_H + +#include "rust-ast-visitor.h" +#include "rust-name-resolver.h" + +#include "rust-diagnostics.h" +#include "rust-location.h" + +namespace Rust { +namespace Resolver { + +class ResolverBase : public AST::ASTVisitor +{ +public: + virtual ~ResolverBase () {} + + // visitor impl + // rust-ast.h + // virtual void visit(AttrInput& attr_input); + // virtual void visit(TokenTree& token_tree); + // virtual void visit(MacroMatch& macro_match); + virtual void visit (AST::Token &tok) {} + virtual void visit (AST::DelimTokenTree &delim_tok_tree) {} + virtual void visit (AST::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // void vsit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (AST::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (AST::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (AST::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (AST::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (AST::PathInExpression &path) {} + virtual void visit (AST::TypePathSegment &segment) {} + virtual void visit (AST::TypePathSegmentGeneric &segment) {} + virtual void visit (AST::TypePathSegmentFunction &segment) {} + virtual void visit (AST::TypePath &path) {} + virtual void visit (AST::QualifiedPathInExpression &path) {} + virtual void visit (AST::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (AST::LiteralExpr &expr) {} + virtual void visit (AST::AttrInputLiteral &attr_input) {} + virtual void visit (AST::MetaItemLitExpr &meta_item) {} + virtual void visit (AST::MetaItemPathLit &meta_item) {} + virtual void visit (AST::BorrowExpr &expr) {} + virtual void visit (AST::DereferenceExpr &expr) {} + virtual void visit (AST::ErrorPropagationExpr &expr) {} + virtual void visit (AST::NegationExpr &expr) {} + virtual void visit (AST::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (AST::ComparisonExpr &expr) {} + virtual void visit (AST::LazyBooleanExpr &expr) {} + virtual void visit (AST::TypeCastExpr &expr) {} + virtual void visit (AST::AssignmentExpr &expr) {} + virtual void visit (AST::CompoundAssignmentExpr &expr) {} + virtual void visit (AST::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (AST::ArrayElemsValues &elems) {} + virtual void visit (AST::ArrayElemsCopied &elems) {} + virtual void visit (AST::ArrayExpr &expr) {} + virtual void visit (AST::ArrayIndexExpr &expr) {} + virtual void visit (AST::TupleExpr &expr) {} + virtual void visit (AST::TupleIndexExpr &expr) {} + virtual void visit (AST::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (AST::StructExprFieldIdentifier &field) {} + virtual void visit (AST::StructExprFieldIdentifierValue &field) {} + virtual void visit (AST::StructExprFieldIndexValue &field) {} + virtual void visit (AST::StructExprStructFields &expr) {} + virtual void visit (AST::StructExprStructBase &expr) {} + virtual void visit (AST::StructExprTuple &expr) {} + virtual void visit (AST::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (AST::EnumExprFieldIdentifier &field) {} + virtual void visit (AST::EnumExprFieldIdentifierValue &field) {} + virtual void visit (AST::EnumExprFieldIndexValue &field) {} + virtual void visit (AST::EnumExprStruct &expr) {} + virtual void visit (AST::EnumExprTuple &expr) {} + virtual void visit (AST::EnumExprFieldless &expr) {} + virtual void visit (AST::CallExpr &expr) {} + virtual void visit (AST::MethodCallExpr &expr) {} + virtual void visit (AST::FieldAccessExpr &expr) {} + virtual void visit (AST::ClosureExprInner &expr) {} + virtual void visit (AST::BlockExpr &expr) {} + virtual void visit (AST::ClosureExprInnerTyped &expr) {} + virtual void visit (AST::ContinueExpr &expr) {} + virtual void visit (AST::BreakExpr &expr) {} + virtual void visit (AST::RangeFromToExpr &expr) {} + virtual void visit (AST::RangeFromExpr &expr) {} + virtual void visit (AST::RangeToExpr &expr) {} + virtual void visit (AST::RangeFullExpr &expr) {} + virtual void visit (AST::RangeFromToInclExpr &expr) {} + virtual void visit (AST::RangeToInclExpr &expr) {} + virtual void visit (AST::ReturnExpr &expr) {} + virtual void visit (AST::UnsafeBlockExpr &expr) {} + virtual void visit (AST::LoopExpr &expr) {} + virtual void visit (AST::WhileLoopExpr &expr) {} + virtual void visit (AST::WhileLetLoopExpr &expr) {} + virtual void visit (AST::ForLoopExpr &expr) {} + virtual void visit (AST::IfExpr &expr) {} + virtual void visit (AST::IfExprConseqElse &expr) {} + virtual void visit (AST::IfExprConseqIf &expr) {} + virtual void visit (AST::IfExprConseqIfLet &expr) {} + virtual void visit (AST::IfLetExpr &expr) {} + virtual void visit (AST::IfLetExprConseqElse &expr) {} + virtual void visit (AST::IfLetExprConseqIf &expr) {} + virtual void visit (AST::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (AST::MatchCaseBlockExpr &match_case) {} + // virtual void visit (AST::MatchCaseExpr &match_case) {} + virtual void visit (AST::MatchExpr &expr) {} + virtual void visit (AST::AwaitExpr &expr) {} + virtual void visit (AST::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (AST::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (AST::LifetimeWhereClauseItem &item) {} + virtual void visit (AST::TypeBoundWhereClauseItem &item) {} + virtual void visit (AST::Method &method) {} + virtual void visit (AST::ModuleBodied &module) {} + virtual void visit (AST::ModuleNoBody &module) {} + virtual void visit (AST::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (AST::UseTreeGlob &use_tree) {} + virtual void visit (AST::UseTreeList &use_tree) {} + virtual void visit (AST::UseTreeRebind &use_tree) {} + virtual void visit (AST::UseDeclaration &use_decl) {} + virtual void visit (AST::Function &function) {} + virtual void visit (AST::TypeAlias &type_alias) {} + virtual void visit (AST::StructStruct &struct_item) {} + virtual void visit (AST::TupleStruct &tuple_struct) {} + virtual void visit (AST::EnumItem &item) {} + virtual void visit (AST::EnumItemTuple &item) {} + virtual void visit (AST::EnumItemStruct &item) {} + virtual void visit (AST::EnumItemDiscriminant &item) {} + virtual void visit (AST::Enum &enum_item) {} + virtual void visit (AST::Union &union_item) {} + virtual void visit (AST::ConstantItem &const_item) {} + virtual void visit (AST::StaticItem &static_item) {} + virtual void visit (AST::TraitItemFunc &item) {} + virtual void visit (AST::TraitItemMethod &item) {} + virtual void visit (AST::TraitItemConst &item) {} + virtual void visit (AST::TraitItemType &item) {} + virtual void visit (AST::Trait &trait) {} + virtual void visit (AST::InherentImpl &impl) {} + virtual void visit (AST::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (AST::ExternalStaticItem &item) {} + virtual void visit (AST::ExternalFunctionItem &item) {} + virtual void visit (AST::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (AST::MacroMatchFragment &match) {} + virtual void visit (AST::MacroMatchRepetition &match) {} + virtual void visit (AST::MacroMatcher &matcher) {} + virtual void visit (AST::MacroRulesDefinition &rules_def) {} + virtual void visit (AST::MacroInvocation ¯o_invoc) {} + virtual void visit (AST::MetaItemPath &meta_item) {} + virtual void visit (AST::MetaItemSeq &meta_item) {} + virtual void visit (AST::MetaWord &meta_item) {} + virtual void visit (AST::MetaNameValueStr &meta_item) {} + virtual void visit (AST::MetaListPaths &meta_item) {} + virtual void visit (AST::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (AST::LiteralPattern &pattern) {} + virtual void visit (AST::IdentifierPattern &pattern) {} + virtual void visit (AST::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (AST::RangePatternBoundLiteral &bound) {} + virtual void visit (AST::RangePatternBoundPath &bound) {} + virtual void visit (AST::RangePatternBoundQualPath &bound) {} + virtual void visit (AST::RangePattern &pattern) {} + virtual void visit (AST::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (AST::StructPatternFieldTuplePat &field) {} + virtual void visit (AST::StructPatternFieldIdentPat &field) {} + virtual void visit (AST::StructPatternFieldIdent &field) {} + virtual void visit (AST::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (AST::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (AST::TupleStructItemsRange &tuple_items) {} + virtual void visit (AST::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (AST::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (AST::TuplePattern &pattern) {} + virtual void visit (AST::GroupedPattern &pattern) {} + virtual void visit (AST::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (AST::EmptyStmt &stmt) {} + virtual void visit (AST::LetStmt &stmt) {} + virtual void visit (AST::ExprStmtWithoutBlock &stmt) {} + virtual void visit (AST::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (AST::TraitBound &bound) {} + virtual void visit (AST::ImplTraitType &type) {} + virtual void visit (AST::TraitObjectType &type) {} + virtual void visit (AST::ParenthesisedType &type) {} + virtual void visit (AST::ImplTraitTypeOneBound &type) {} + virtual void visit (AST::TraitObjectTypeOneBound &type) {} + virtual void visit (AST::TupleType &type) {} + virtual void visit (AST::NeverType &type) {} + virtual void visit (AST::RawPointerType &type) {} + virtual void visit (AST::ReferenceType &type) {} + virtual void visit (AST::ArrayType &type) {} + virtual void visit (AST::SliceType &type) {} + virtual void visit (AST::InferredType &type) {} + virtual void visit (AST::BareFunctionType &type) {} + +protected: + ResolverBase (NodeId parent) + : resolver (Resolver::get ()), resolved_node (UNKNOWN_NODEID), + parent (parent), locus (Location ()) + {} + + bool resolved () const { return resolved_node != UNKNOWN_NODEID; } + + Resolver *resolver; + NodeId resolved_node; + NodeId parent; + Location locus; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_BASE_H diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h new file mode 100644 index 0000000..9ca763d --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -0,0 +1,98 @@ +// 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 +// . + +#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)) + { + 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_return_expr ()) + ResolveExpr::go (expr.get_expr (), expr.get_node_id ()); + } + + void visit (AST::CallExpr &expr) + { + ResolveExpr::go (expr.function.get (), expr.get_node_id ()); + expr.iterate_params ([&] (AST::Expr *p) mutable -> bool { + ResolveExpr::go (p, expr.get_node_id ()); + return true; + }); + } + + void visit (AST::AssignmentExpr &expr) + { + ResolveExpr::go (expr.get_lhs (), expr.get_node_id ()); + ResolveExpr::go (expr.get_rhs (), 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_lhs (), expr.get_node_id ()); + ResolveExpr::go (expr.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..ea79fc0 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -0,0 +1,68 @@ +// 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 +// . + +#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" + +namespace Rust { +namespace Resolver { + +class ResolveItem : public ResolverBase +{ +public: + static void go (AST::Item *item) + { + ResolveItem resolver; + item->accept_vis (resolver); + }; + + ~ResolveItem () {} + + void visit (AST::Function &function) + { + if (function.has_return_type ()) + ResolveType::go (function.get_return_type ().get (), + function.get_node_id ()); + + for (auto ¶m : function.get_function_params ()) + { + ResolveType::go (param.get_type ().get (), param.get_node_id ()); + PatternDeclaration::go (param.get_pattern ().get (), + param.get_node_id ()); + } + + function.get_definition ()->iterate_stmts ( + [&] (AST::Stmt *s) mutable -> bool { + // TODO + return true; + }); + } + +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 +// . + +#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..42fb097 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -0,0 +1,59 @@ +// 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 +// . + +#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::LetStmt &stmt) + { + PatternDeclaration::go (stmt.variables_pattern.get (), stmt.get_node_id ()); + if (stmt.has_type ()) + ResolveType::go (stmt.type.get (), stmt.get_node_id ()); + + if (stmt.has_init_expr ()) + ResolveExpr::go (stmt.init_expr.get (), stmt.get_node_id ()); + } + +private: + ResolveStmt () : ResolverBase (UNKNOWN_NODEID) {} +}; + +} // 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 +// . + +#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 +// . + +#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..664af12 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -0,0 +1,245 @@ +// 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 +// . + +#include "rust-ast-resolve.h" +#include "rust-ast-resolve-toplevel.h" +#include "rust-ast-resolve-item.h" +#include "rust-ast-full.h" + +#define MKBUILTIN_TYPE(_X, _R) \ + do \ + { \ + AST::PathIdentSegment seg (_X); \ + auto typePath = ::std::unique_ptr ( \ + new AST::TypePathSegment (::std::move (seg), false, \ + Linemap::predeclared_location ())); \ + ::std::vector< ::std::unique_ptr > 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); \ + } \ + while (0) + +namespace Rust { +namespace Resolver { + +// Resolver + +Resolver::Resolver () + : mappings (Analysis::Mappings::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 & +Resolver::get_builtin_types () +{ + return builtins; +} + +void +Resolver::generate_builtins () +{ + MKBUILTIN_TYPE ("u8", builtins); + MKBUILTIN_TYPE ("u16", builtins); + MKBUILTIN_TYPE ("u32", builtins); + MKBUILTIN_TYPE ("u64", builtins); + + MKBUILTIN_TYPE ("i8", builtins); + MKBUILTIN_TYPE ("i16", builtins); + MKBUILTIN_TYPE ("i32", builtins); + MKBUILTIN_TYPE ("i64", builtins); + + MKBUILTIN_TYPE ("f32", builtins); + MKBUILTIN_TYPE ("f64", builtins); + + MKBUILTIN_TYPE ("char", builtins); + MKBUILTIN_TYPE ("str", builtins); + MKBUILTIN_TYPE ("bool", builtins); +} + +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 +// . + +#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..4aac7d5 --- /dev/null +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -0,0 +1,211 @@ +// 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 +// . + +#ifndef RUST_NAME_RESOLVER_H +#define RUST_NAME_RESOLVER_H + +#include "rust-system.h" +#include "rust-hir-map.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; } + +private: + CrateNum crate_num; + NodeId node_id; + std::map mappings; + std::set 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 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 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 &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; + + std::vector builtins; + + Scope name_scope; + Scope type_scope; + + NodeId global_type_node_id; + + // map a AST Node to a Rib + std::map name_ribs; + std::map type_ribs; + + // map any Node to its Definition + // ie any name or type usage + std::map 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 resolved_names; + std::map resolved_types; + + std::map > nameDefNodeIdToRibs; + std::map > 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 f526da1..3131af0 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -29,14 +29,13 @@ #include "rust-lex.h" #include "rust-parse.h" #include "rust-scan.h" -#include "rust-name-resolution.h" -#include "rust-type-resolution.h" #include "rust-macro-expand.h" #include "rust-compile.h" +#include "rust-target.h" // hir passes wip +#include "rust-ast-resolve.h" #include "rust-ast-lower.h" -#include "rust-target.h" extern Linemap * rust_get_linemap (); @@ -399,6 +398,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 " @@ -527,6 +530,17 @@ Session::parse_file (const char *filename) // TODO: what do I dump here? resolved names? AST with resolved names? } + // lower AST to HIR + HIR::Crate hir = HIR::ASTLowering::Resolve (parsed_crate); + if (options.dump_option == CompileOptions::HIR_DUMP) + { + fprintf (stderr, "%s", hir.as_string ().c_str ()); + return; + } + + // type resolve + // TODO + if (saw_errors ()) return; @@ -759,16 +773,7 @@ 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); - - // inject hir passes - HIR::Crate hir = HIR::ASTLowering::Resolve (crate); - fprintf (stderr, "HIR PASSES:\n"); - fprintf (stderr, "%s", hir.as_string ().c_str ()); - fprintf (stderr, "HIR PASSES - DONE:\n"); + Resolver::NameResolution::Resolve (crate); fprintf (stderr, "finished name resolution\n"); } diff --git a/gcc/rust/rust-session-manager.h b/gcc/rust/rust-session-manager.h index bdeeeec..2bb1dfb 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 +// . +// #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 -#include -#include -#include -#include - namespace Rust { // parser forward decl template class Parser; @@ -32,7 +44,7 @@ struct TargetOptions { /* TODO: maybe make private and access through helpers to allow changes to * impl */ - std::unordered_map> features; + std::unordered_map > features; public: // Returns whether a key is defined in the feature set. @@ -160,6 +172,7 @@ struct CompileOptions EXPANSION_DUMP, RESOLUTION_DUMP, TARGET_OPTION_DUMP, + HIR_DUMP, // TODO: add more? } dump_option; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index ff3e548..094d0e3 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -64,10 +64,16 @@ NodeMapping::get_local_defid () const 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 |= get_crate_num (); + val |= crate_num; val = val << sizeof (uint32_t); - val |= get_local_defid (); + val |= local_defid; return val; } diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index cbe22a5..8929ca4 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -63,6 +63,8 @@ public: 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: @@ -126,6 +128,9 @@ private: std::map > localDefIdMappings; std::map > hirItemMappings; std::map > hirExprMappings; + + // reverse mappings + std::map > nodeIdToHirMappings; }; } // namespace Analysis -- cgit v1.1 From 44d10d9547612b5fda3d27bb628d5d6ee79108af Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Sat, 12 Dec 2020 12:56:02 +0000 Subject: TypeResolution pass now with a TyTy module Resolution must implement the Gathering specified in the rust-dev guide. We need to be able to handle cases such as: let mut x; x = 1; or let mut x = vec!{} x.push(1) Now the TyTy module has a combine abstract method to allow the combination of types to condense down from their integral parts. --- gcc/rust/Make-lang.in | 13 +- gcc/rust/hir/rust-ast-lower-item.h | 2 + gcc/rust/hir/rust-ast-lower-stmt.h | 4 + gcc/rust/hir/rust-ast-lower-type.h | 9 +- gcc/rust/hir/tree/rust-hir-expr.h | 13 ++ gcc/rust/hir/tree/rust-hir-item.h | 29 --- gcc/rust/hir/tree/rust-hir-macro.h | 3 +- gcc/rust/hir/tree/rust-hir-path.h | 31 ++- gcc/rust/hir/tree/rust-hir-stmt.h | 4 + gcc/rust/hir/tree/rust-hir-type.h | 105 +++++---- gcc/rust/hir/tree/rust-hir.h | 8 + gcc/rust/resolve/rust-ast-resolve-expr.h | 15 +- gcc/rust/resolve/rust-ast-resolve-item.h | 13 +- gcc/rust/resolve/rust-ast-resolve-pattern.h | 1 + gcc/rust/resolve/rust-ast-resolve-stmt.h | 8 +- gcc/rust/resolve/rust-ast-resolve.cc | 43 ++-- gcc/rust/resolve/rust-name-resolver.h | 11 + gcc/rust/rust-session-manager.cc | 30 ++- gcc/rust/rust-session-manager.h | 9 + gcc/rust/typecheck/rust-hir-type-check-base.h | 256 ++++++++++++++++++++++ gcc/rust/typecheck/rust-hir-type-check-expr.h | 173 +++++++++++++++ gcc/rust/typecheck/rust-hir-type-check-item.h | 90 ++++++++ gcc/rust/typecheck/rust-hir-type-check-stmt.h | 86 ++++++++ gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 63 ++++++ gcc/rust/typecheck/rust-hir-type-check-type.h | 81 +++++++ gcc/rust/typecheck/rust-hir-type-check.cc | 38 ++++ gcc/rust/typecheck/rust-hir-type-check.h | 66 ++++++ gcc/rust/typecheck/rust-tyctx.cc | 104 +++++++++ gcc/rust/typecheck/rust-tyty-call.h | 53 +++++ gcc/rust/typecheck/rust-tyty-rules.h | 241 ++++++++++++++++++++ gcc/rust/typecheck/rust-tyty-visitor.h | 42 ++++ gcc/rust/typecheck/rust-tyty.cc | 223 +++++++++++++++++++ gcc/rust/typecheck/rust-tyty.h | 208 ++++++++++++++++++ gcc/rust/util/rust-hir-map.cc | 65 +++++- gcc/rust/util/rust-hir-map.h | 30 ++- gcc/rust/util/rust-inference-var.h | 112 ---------- 36 files changed, 2039 insertions(+), 243 deletions(-) create mode 100644 gcc/rust/typecheck/rust-hir-type-check-base.h create mode 100644 gcc/rust/typecheck/rust-hir-type-check-expr.h create mode 100644 gcc/rust/typecheck/rust-hir-type-check-item.h create mode 100644 gcc/rust/typecheck/rust-hir-type-check-stmt.h create mode 100644 gcc/rust/typecheck/rust-hir-type-check-toplevel.h create mode 100644 gcc/rust/typecheck/rust-hir-type-check-type.h create mode 100644 gcc/rust/typecheck/rust-hir-type-check.cc create mode 100644 gcc/rust/typecheck/rust-hir-type-check.h create mode 100644 gcc/rust/typecheck/rust-tyctx.cc create mode 100644 gcc/rust/typecheck/rust-tyty-call.h create mode 100644 gcc/rust/typecheck/rust-tyty-rules.h create mode 100644 gcc/rust/typecheck/rust-tyty-visitor.h create mode 100644 gcc/rust/typecheck/rust-tyty.cc create mode 100644 gcc/rust/typecheck/rust-tyty.h delete mode 100644 gcc/rust/util/rust-inference-var.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index aa81813..96457ed 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -78,6 +78,9 @@ GRS_OBJS = \ 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 @@ -231,7 +234,8 @@ RUST_INCLUDES = -I $(srcdir)/rust \ -I $(srcdir)/rust/hir/tree \ -I $(srcdir)/rust/hir \ -I $(srcdir)/rust/resolve \ - -I $(srcdir)/rust/util + -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) @@ -287,8 +291,13 @@ rust/%.o: rust/hir/tree/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) -# build rust/hir/tree files in rust folder +# 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/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index 71e465e..e0ce862 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -93,6 +93,8 @@ public: mappings->insert_defid_mapping (mapping.get_defid (), translated); mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), translated); + mappings->insert_location (crate_num, mapping.get_hirid (), + function.get_locus ()); } // Helpers diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h index d18dc19..c813639 100644 --- a/gcc/rust/hir/rust-ast-lower-stmt.h +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -58,6 +58,8 @@ public: = new HIR::ExprStmtWithoutBlock (mapping, std::unique_ptr (expr), stmt.get_locus ()); + mappings->insert_location (crate_num, mapping.get_hirid (), + stmt.get_locus ()); } void visit (AST::LetStmt &stmt) @@ -82,6 +84,8 @@ public: std::unique_ptr (init_expression), std::unique_ptr (type), std::move (outer_attrs), stmt.get_locus ()); + mappings->insert_location (crate_num, mapping.get_hirid (), + stmt.get_locus ()); } private: diff --git a/gcc/rust/hir/rust-ast-lower-type.h b/gcc/rust/hir/rust-ast-lower-type.h index 9611ca0..4193415 100644 --- a/gcc/rust/hir/rust-ast-lower-type.h +++ b/gcc/rust/hir/rust-ast-lower-type.h @@ -65,9 +65,16 @@ public: 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 (translated_segments), path.get_locus (), + = 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: diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index 5f5bbf9..b08aa91 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -2169,6 +2169,8 @@ public: Expr *get_fnexpr () { return function.get (); } + size_t num_params () const { return params.size (); } + void iterate_params (std::function cb) { for (auto it = params.begin (); it != params.end (); it++) @@ -2551,6 +2553,15 @@ public: void accept_vis (HIRVisitor &vis) override; + void iterate_stmts (std::function cb) + { + for (auto it = statements.begin (); it != statements.end (); it++) + { + if (!cb (it->get ())) + return; + } + } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ @@ -3118,6 +3129,8 @@ public: 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 */ diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index 774e407..cf24bae 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -319,19 +319,6 @@ public: // not having either is not an error } - // Creates an error state self-param. - static SelfParam create_error () - { - /* HACK: creates a dummy type. Since it's a unique pointer, it should - * clean it up, but it still allocates memory, which is not ideal. */ - return SelfParam (Lifetime (Lifetime::STATIC), false, false, - new QualifiedPathInType ( - QualifiedPathInType::create_error ())); - /* FIXME: is there a reason why I didn't just create a null pointer? Is it - * due to error being having both a type and a lifetime? If it is, wouldn't - * something like "not has_ref and has lifetime" for error be better? */ - } - // Type-based self parameter (not ref, no lifetime) SelfParam (std::unique_ptr type, bool is_mut, Location locus) : has_ref (false), is_mut (is_mut), lifetime (Lifetime::error ()), @@ -588,22 +575,6 @@ class Method : public InherentImplItem, public TraitImplItem Location locus; public: - // Returns whether the method is in an error state. - bool is_error () const - { - return expr == nullptr || method_name.empty () || self_param.is_error (); - } - - // Creates an error state method. - static Method create_error () - { - return Method ("", FunctionQualifiers (FunctionQualifiers::NONE, true), - std::vector > (), - SelfParam::create_error (), std::vector (), - nullptr, WhereClause::create_empty (), nullptr, - Visibility::create_error (), std::vector ()); - } - // Returns whether the method has generic parameters. bool has_generics () const { return !generic_params.empty (); } diff --git a/gcc/rust/hir/tree/rust-hir-macro.h b/gcc/rust/hir/tree/rust-hir-macro.h index 0a38134..84b4914 100644 --- a/gcc/rust/hir/tree/rust-hir-macro.h +++ b/gcc/rust/hir/tree/rust-hir-macro.h @@ -345,7 +345,8 @@ public: MacroInvocation (Analysis::NodeMapping mappings, SimplePath path, DelimTokenTree token_tree, std::vector outer_attrs, Location locus) - : ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), + : TypeNoBounds (mappings), + ExprWithoutBlock (std::move (mappings), std::move (outer_attrs)), path (std::move (path)), token_tree (std::move (token_tree)), locus (locus) {} diff --git a/gcc/rust/hir/tree/rust-hir-path.h b/gcc/rust/hir/tree/rust-hir-path.h index 06d31aa..1bba506 100644 --- a/gcc/rust/hir/tree/rust-hir-path.h +++ b/gcc/rust/hir/tree/rust-hir-path.h @@ -591,20 +591,24 @@ public: // Creates an error state TypePath. static TypePath create_error () { - return TypePath (std::vector > (), + return TypePath (Analysis::NodeMapping::get_error (), + std::vector > (), Location ()); } // Constructor - TypePath (std::vector > segments, + TypePath (Analysis::NodeMapping mappings, + std::vector > segments, Location locus, bool has_opening_scope_resolution = false) - : has_opening_scope_resolution (has_opening_scope_resolution), + : 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) - : has_opening_scope_resolution (other.has_opening_scope_resolution), + : TypeNoBounds (other.mappings), + has_opening_scope_resolution (other.has_opening_scope_resolution), locus (other.locus) { segments.reserve (other.segments.size ()); @@ -617,6 +621,7 @@ public: { 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) @@ -793,10 +798,10 @@ protected: public: QualifiedPathInType ( - QualifiedPathType qual_path_type, + Analysis::NodeMapping mappings, QualifiedPathType qual_path_type, std::vector > path_segments, Location locus = Location ()) - : path_type (std::move (qual_path_type)), + : TypeNoBounds (mappings), path_type (std::move (qual_path_type)), segments (std::move (path_segments)), locus (locus) {} @@ -805,7 +810,7 @@ public: // Copy constructor with vector clone QualifiedPathInType (QualifiedPathInType const &other) - : path_type (other.path_type), locus (other.locus) + : TypeNoBounds (mappings), path_type (other.path_type), locus (other.locus) { segments.reserve (other.segments.size ()); for (const auto &e : other.segments) @@ -817,6 +822,7 @@ public: { path_type = other.path_type; locus = other.locus; + mappings = other.mappings; segments.reserve (other.segments.size ()); for (const auto &e : other.segments) @@ -829,17 +835,6 @@ public: QualifiedPathInType (QualifiedPathInType &&other) = default; QualifiedPathInType &operator= (QualifiedPathInType &&other) = default; - // Returns whether qualified path in type is in an error state. - bool is_error () const { return path_type.is_error (); } - - // Creates an error state qualified path in type. - static QualifiedPathInType create_error () - { - return QualifiedPathInType ( - QualifiedPathType::create_error (), - std::vector > ()); - } - std::string as_string () const override; void accept_vis (HIRVisitor &vis) override; diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h index 61d9dcb..31d55b6 100644 --- a/gcc/rust/hir/tree/rust-hir-stmt.h +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -113,6 +113,10 @@ public: void accept_vis (HIRVisitor &vis) override; + HIR::Type *get_type () { return type.get (); } + + HIR::Expr *get_init_expr () { return init_expr.get (); } + protected: /* Use covariance to implement clone function as returning this object rather * than base */ diff --git a/gcc/rust/hir/tree/rust-hir-type.h b/gcc/rust/hir/tree/rust-hir-type.h index 0a446bd..f8c851c 100644 --- a/gcc/rust/hir/tree/rust-hir-type.h +++ b/gcc/rust/hir/tree/rust-hir-type.h @@ -92,13 +92,16 @@ protected: public: ImplTraitType ( + Analysis::NodeMapping mappings, std::vector > type_param_bounds, Location locus) - : type_param_bounds (std::move (type_param_bounds)), locus (locus) + : Type (mappings), type_param_bounds (std::move (type_param_bounds)), + locus (locus) {} // copy constructor with vector clone - ImplTraitType (ImplTraitType const &other) : locus (other.locus) + 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) @@ -109,6 +112,7 @@ public: 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) @@ -148,15 +152,16 @@ protected: public: TraitObjectType ( + Analysis::NodeMapping mappings, std::vector > type_param_bounds, Location locus, bool is_dyn_dispatch = false) - : has_dyn (is_dyn_dispatch), + : 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) - : has_dyn (other.has_dyn), locus (other.locus) + : 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) @@ -166,6 +171,7 @@ public: // 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 ()); @@ -209,19 +215,23 @@ protected: public: // Constructor uses Type pointer for polymorphism - ParenthesisedType (std::unique_ptr type_inside_parens, Location locus) - : type_in_parens (std::move (type_inside_parens)), locus (locus) + ParenthesisedType (Analysis::NodeMapping mappings, + std::unique_ptr 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) - : type_in_parens (other.type_in_parens->clone_type ()), locus (other.locus) + : 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; @@ -273,8 +283,10 @@ protected: } public: - ImplTraitTypeOneBound (TraitBound trait_bound, Location locus) - : trait_bound (std::move (trait_bound)), locus (locus) + 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; @@ -309,10 +321,11 @@ protected: } public: - TraitObjectTypeOneBound (TraitBound trait_bound, Location locus, + TraitObjectTypeOneBound (Analysis::NodeMapping mappings, + TraitBound trait_bound, Location locus, bool is_dyn_dispatch = false) - : has_dyn (is_dyn_dispatch), trait_bound (std::move (trait_bound)), - locus (locus) + : TypeNoBounds (mappings), has_dyn (is_dyn_dispatch), + trait_bound (std::move (trait_bound)), locus (locus) {} std::string as_string () const override; @@ -343,13 +356,16 @@ public: // Returns whether the tuple type is the unit type, i.e. has no elements. bool is_unit_type () const { return elems.empty (); } - TupleType (std::vector > elems, Location locus) - : elems (std::move (elems)), locus (locus) + TupleType (Analysis::NodeMapping mappings, + std::vector > elems, Location locus) + : TypeNoBounds (mappings), elems (std::move (elems)), locus (locus) {} // copy constructor with vector clone - TupleType (TupleType const &other) : locus (other.locus) + 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 ()); @@ -410,7 +426,9 @@ protected: } public: - NeverType (Location locus) : locus (locus) {} + NeverType (Analysis::NodeMapping mappings, Location locus) + : TypeNoBounds (mappings), locus (locus) + {} std::string as_string () const override { return "! (never type)"; } @@ -439,21 +457,22 @@ public: PointerType get_pointer_type () const { return pointer_type; } // Constructor requires pointer for polymorphism reasons - RawPointerType (PointerType pointer_type, + RawPointerType (Analysis::NodeMapping mappings, PointerType pointer_type, std::unique_ptr type_no_bounds, Location locus) - : pointer_type (pointer_type), type (std::move (type_no_bounds)), - locus (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) - : pointer_type (other.pointer_type), + : 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; @@ -504,21 +523,24 @@ public: bool has_lifetime () const { return !lifetime.is_error (); } // Constructor - ReferenceType (bool is_mut, std::unique_ptr type_no_bounds, - Location locus, Lifetime lifetime = Lifetime::error ()) - : lifetime (std::move (lifetime)), has_mut (is_mut), - type (std::move (type_no_bounds)), locus (locus) + ReferenceType (Analysis::NodeMapping mappings, bool is_mut, + std::unique_ptr 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) - : lifetime (other.lifetime), has_mut (other.has_mut), - type (other.type->clone_type_no_bounds ()), locus (other.locus) + : 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 (); @@ -562,20 +584,22 @@ class ArrayType : public TypeNoBounds public: // Constructor requires pointers for polymorphism - ArrayType (std::unique_ptr type, std::unique_ptr array_size, - Location locus) - : elem_type (std::move (type)), size (std::move (array_size)), locus (locus) + ArrayType (Analysis::NodeMapping mappings, std::unique_ptr type, + std::unique_ptr 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) - : elem_type (other.elem_type->clone_type ()), + : 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; @@ -620,18 +644,21 @@ class SliceType : public TypeNoBounds public: // Constructor requires pointer for polymorphism - SliceType (std::unique_ptr type, Location locus) - : elem_type (std::move (type)), locus (locus) + SliceType (Analysis::NodeMapping mappings, std::unique_ptr 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) - : elem_type (other.elem_type->clone_type ()), locus (other.locus) + : 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; @@ -684,7 +711,9 @@ protected: } public: - InferredType (Location locus) : locus (locus) {} + InferredType (Analysis::NodeMapping mappings, Location locus) + : TypeNoBounds (mappings), locus (locus) + {} std::string as_string () const override; @@ -783,11 +812,12 @@ public: // Whether the function has ForLifetimes. bool has_for_lifetimes () const { return !for_lifetimes.empty (); } - BareFunctionType (std::vector lifetime_params, + BareFunctionType (Analysis::NodeMapping mappings, + std::vector lifetime_params, FunctionQualifiers qualifiers, std::vector named_params, bool is_variadic, std::unique_ptr type, Location locus) - : for_lifetimes (std::move (lifetime_params)), + : 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) @@ -795,7 +825,7 @@ public: // Copy constructor with clone BareFunctionType (BareFunctionType const &other) - : for_lifetimes (other.for_lifetimes), + : 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 ()), @@ -805,6 +835,7 @@ public: // 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; diff --git a/gcc/rust/hir/tree/rust-hir.h b/gcc/rust/hir/tree/rust-hir.h index b7feb59..cbaa2e9 100644 --- a/gcc/rust/hir/tree/rust-hir.h +++ b/gcc/rust/hir/tree/rust-hir.h @@ -968,9 +968,15 @@ public: 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 @@ -984,6 +990,8 @@ public: } protected: + TypeNoBounds (Analysis::NodeMapping mappings) : Type (mappings) {} + // Clone function implementation as pure virtual method virtual TypeNoBounds *clone_type_no_bounds_impl () const = 0; diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index 9ca763d..b9e7f6a 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -49,23 +49,24 @@ public: void visit (AST::ReturnExpr &expr) { - if (expr.has_return_expr ()) - ResolveExpr::go (expr.get_expr (), expr.get_node_id ()); + if (expr.has_returned_expr ()) + ResolveExpr::go (expr.get_returned_expr ().get (), expr.get_node_id ()); } void visit (AST::CallExpr &expr) { - ResolveExpr::go (expr.function.get (), expr.get_node_id ()); + 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_lhs (), expr.get_node_id ()); - ResolveExpr::go (expr.get_rhs (), expr.get_node_id ()); + 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) @@ -84,8 +85,8 @@ public: void visit (AST::ArithmeticOrLogicalExpr &expr) { - ResolveExpr::go (expr.get_lhs (), expr.get_node_id ()); - ResolveExpr::go (expr.right_expr.get (), expr.get_node_id ()); + ResolveExpr::go (expr.get_left_expr ().get (), expr.get_node_id ()); + ResolveExpr::go (expr.get_right_expr ().get (), expr.get_node_id ()); } private: diff --git a/gcc/rust/resolve/rust-ast-resolve-item.h b/gcc/rust/resolve/rust-ast-resolve-item.h index ea79fc0..2c21a52 100644 --- a/gcc/rust/resolve/rust-ast-resolve-item.h +++ b/gcc/rust/resolve/rust-ast-resolve-item.h @@ -23,6 +23,7 @@ #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 { @@ -51,11 +52,21 @@ public: 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 { - // TODO + ResolveStmt::go (s, s->get_node_id ()); return true; }); + + resolver->get_name_scope ().pop (); + resolver->get_type_scope ().pop (); } private: diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index fc2da70..a393d31 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -78,6 +78,7 @@ public: void visit (AST::IdentifierPattern &pattern) { + printf ("declaration for: %s\n", pattern.as_string ().c_str ()); // 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 (), diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 42fb097..623fbd4 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -41,16 +41,16 @@ public: void visit (AST::LetStmt &stmt) { - PatternDeclaration::go (stmt.variables_pattern.get (), stmt.get_node_id ()); + PatternDeclaration::go (stmt.get_pattern ().get (), stmt.get_node_id ()); if (stmt.has_type ()) - ResolveType::go (stmt.type.get (), stmt.get_node_id ()); + ResolveType::go (stmt.get_type ().get (), stmt.get_node_id ()); if (stmt.has_init_expr ()) - ResolveExpr::go (stmt.init_expr.get (), stmt.get_node_id ()); + ResolveExpr::go (stmt.get_init_expr ().get (), stmt.get_node_id ()); } private: - ResolveStmt () : ResolverBase (UNKNOWN_NODEID) {} + ResolveStmt (NodeId parent) : ResolverBase (parent) {} }; } // namespace Resolver diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc index 664af12..57bd0f3 100644 --- a/gcc/rust/resolve/rust-ast-resolve.cc +++ b/gcc/rust/resolve/rust-ast-resolve.cc @@ -20,8 +20,9 @@ #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) \ +#define MKBUILTIN_TYPE(_X, _R, _TY) \ do \ { \ AST::PathIdentSegment seg (_X); \ @@ -34,6 +35,8 @@ = 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) @@ -43,7 +46,7 @@ namespace Resolver { // Resolver Resolver::Resolver () - : mappings (Analysis::Mappings::get ()), + : mappings (Analysis::Mappings::get ()), tyctx (TypeCheckContext::get ()), name_scope (Scope (mappings->get_current_crate ())), type_scope (Scope (mappings->get_current_crate ())) { @@ -116,22 +119,26 @@ Resolver::get_builtin_types () void Resolver::generate_builtins () { - MKBUILTIN_TYPE ("u8", builtins); - MKBUILTIN_TYPE ("u16", builtins); - MKBUILTIN_TYPE ("u32", builtins); - MKBUILTIN_TYPE ("u64", builtins); - - MKBUILTIN_TYPE ("i8", builtins); - MKBUILTIN_TYPE ("i16", builtins); - MKBUILTIN_TYPE ("i32", builtins); - MKBUILTIN_TYPE ("i64", builtins); - - MKBUILTIN_TYPE ("f32", builtins); - MKBUILTIN_TYPE ("f64", builtins); - - MKBUILTIN_TYPE ("char", builtins); - MKBUILTIN_TYPE ("str", builtins); - MKBUILTIN_TYPE ("bool", 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 diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h index 4aac7d5..2aa592c 100644 --- a/gcc/rust/resolve/rust-name-resolver.h +++ b/gcc/rust/resolve/rust-name-resolver.h @@ -21,6 +21,7 @@ #include "rust-system.h" #include "rust-hir-map.h" +#include "rust-hir-type-check.h" namespace Rust { namespace Resolver { @@ -55,6 +56,15 @@ public: CrateNum get_crate_num () const { return crate_num; } NodeId get_node_id () const { return node_id; } + void iterate_decls (std::function cb) + { + for (auto it : decls_within_rib) + { + if (!cb (it)) + return; + } + } + private: CrateNum crate_num; NodeId node_id; @@ -174,6 +184,7 @@ private: void generate_builtins (); Analysis::Mappings *mappings; + TypeCheckContext *tyctx; std::vector builtins; diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index 3131af0..fc64994 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -26,16 +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-macro-expand.h" -#include "rust-compile.h" -#include "rust-target.h" - -// hir passes wip #include "rust-ast-resolve.h" #include "rust-ast-lower.h" +#include "rust-hir-type-check.h" extern Linemap * rust_get_linemap (); @@ -531,7 +530,7 @@ Session::parse_file (const char *filename) } // lower AST to HIR - HIR::Crate hir = HIR::ASTLowering::Resolve (parsed_crate); + HIR::Crate hir = lower_ast (parsed_crate); if (options.dump_option == CompileOptions::HIR_DUMP) { fprintf (stderr, "%s", hir.as_string ().c_str ()); @@ -539,13 +538,13 @@ Session::parse_file (const char *filename) } // type resolve - // TODO + type_resolution (hir); if (saw_errors ()) return; // do compile - Compile::Compilation::Compile (parsed_crate, backend); + // Compile::Compilation::Compile (parsed_crate, backend); } // TODO: actually implement method @@ -777,6 +776,23 @@ Session::resolution (AST::Crate &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 2bb1dfb..4836cc8 100644 --- a/gcc/rust/rust-session-manager.h +++ b/gcc/rust/rust-session-manager.h @@ -37,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. */ @@ -240,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/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 +// . + +#ifndef RUST_HIR_TYPE_CHECK_BASE +#define RUST_HIR_TYPE_CHECK_BASE + +#include "rust-diagnostics.h" +#include "rust-hir-type-check.h" +#include "rust-name-resolver.h" +#include "rust-hir-visitor.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace Resolver { + +// base class to allow derivatives to overload as needed +class TypeCheckBase : public HIR::HIRVisitor +{ +public: + virtual ~TypeCheckBase () {} + + // visitor impl + // rust-ast.h + // virtual void visit(AttrInput& attr_input); + // virtual void visit(TokenTree& token_tree); + // virtual void visit(MacroMatch& macro_match); + virtual void visit (HIR::Token &tok) {} + virtual void visit (HIR::DelimTokenTree &delim_tok_tree) {} + virtual void visit (HIR::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // void vsit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (HIR::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (HIR::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (HIR::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (HIR::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (HIR::PathInExpression &path) {} + virtual void visit (HIR::TypePathSegment &segment) {} + virtual void visit (HIR::TypePathSegmentGeneric &segment) {} + virtual void visit (HIR::TypePathSegmentFunction &segment) {} + virtual void visit (HIR::TypePath &path) {} + virtual void visit (HIR::QualifiedPathInExpression &path) {} + virtual void visit (HIR::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (HIR::LiteralExpr &expr) {} + virtual void visit (HIR::AttrInputLiteral &attr_input) {} + virtual void visit (HIR::MetaItemLitExpr &meta_item) {} + virtual void visit (HIR::MetaItemPathLit &meta_item) {} + virtual void visit (HIR::BorrowExpr &expr) {} + virtual void visit (HIR::DereferenceExpr &expr) {} + virtual void visit (HIR::ErrorPropagationExpr &expr) {} + virtual void visit (HIR::NegationExpr &expr) {} + virtual void visit (HIR::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (HIR::ComparisonExpr &expr) {} + virtual void visit (HIR::LazyBooleanExpr &expr) {} + virtual void visit (HIR::TypeCastExpr &expr) {} + virtual void visit (HIR::AssignmentExpr &expr) {} + virtual void visit (HIR::CompoundAssignmentExpr &expr) {} + virtual void visit (HIR::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (HIR::ArrayElemsValues &elems) {} + virtual void visit (HIR::ArrayElemsCopied &elems) {} + virtual void visit (HIR::ArrayExpr &expr) {} + virtual void visit (HIR::ArrayIndexExpr &expr) {} + virtual void visit (HIR::TupleExpr &expr) {} + virtual void visit (HIR::TupleIndexExpr &expr) {} + virtual void visit (HIR::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (HIR::StructExprFieldIdentifier &field) {} + virtual void visit (HIR::StructExprFieldIdentifierValue &field) {} + virtual void visit (HIR::StructExprFieldIndexValue &field) {} + virtual void visit (HIR::StructExprStructFields &expr) {} + virtual void visit (HIR::StructExprStructBase &expr) {} + virtual void visit (HIR::StructExprTuple &expr) {} + virtual void visit (HIR::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (HIR::EnumExprFieldIdentifier &field) {} + virtual void visit (HIR::EnumExprFieldIdentifierValue &field) {} + virtual void visit (HIR::EnumExprFieldIndexValue &field) {} + virtual void visit (HIR::EnumExprStruct &expr) {} + virtual void visit (HIR::EnumExprTuple &expr) {} + virtual void visit (HIR::EnumExprFieldless &expr) {} + virtual void visit (HIR::CallExpr &expr) {} + virtual void visit (HIR::MethodCallExpr &expr) {} + virtual void visit (HIR::FieldAccessExpr &expr) {} + virtual void visit (HIR::ClosureExprInner &expr) {} + virtual void visit (HIR::BlockExpr &expr) {} + virtual void visit (HIR::ClosureExprInnerTyped &expr) {} + virtual void visit (HIR::ContinueExpr &expr) {} + virtual void visit (HIR::BreakExpr &expr) {} + virtual void visit (HIR::RangeFromToExpr &expr) {} + virtual void visit (HIR::RangeFromExpr &expr) {} + virtual void visit (HIR::RangeToExpr &expr) {} + virtual void visit (HIR::RangeFullExpr &expr) {} + virtual void visit (HIR::RangeFromToInclExpr &expr) {} + virtual void visit (HIR::RangeToInclExpr &expr) {} + virtual void visit (HIR::ReturnExpr &expr) {} + virtual void visit (HIR::UnsafeBlockExpr &expr) {} + virtual void visit (HIR::LoopExpr &expr) {} + virtual void visit (HIR::WhileLoopExpr &expr) {} + virtual void visit (HIR::WhileLetLoopExpr &expr) {} + virtual void visit (HIR::ForLoopExpr &expr) {} + virtual void visit (HIR::IfExpr &expr) {} + virtual void visit (HIR::IfExprConseqElse &expr) {} + virtual void visit (HIR::IfExprConseqIf &expr) {} + virtual void visit (HIR::IfExprConseqIfLet &expr) {} + virtual void visit (HIR::IfLetExpr &expr) {} + virtual void visit (HIR::IfLetExprConseqElse &expr) {} + virtual void visit (HIR::IfLetExprConseqIf &expr) {} + virtual void visit (HIR::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (HIR::MatchCaseBlockExpr &match_case) {} + // virtual void visit (HIR::MatchCaseExpr &match_case) {} + virtual void visit (HIR::MatchExpr &expr) {} + virtual void visit (HIR::AwaitExpr &expr) {} + virtual void visit (HIR::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (HIR::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (HIR::LifetimeWhereClauseItem &item) {} + virtual void visit (HIR::TypeBoundWhereClauseItem &item) {} + virtual void visit (HIR::Method &method) {} + virtual void visit (HIR::ModuleBodied &module) {} + virtual void visit (HIR::ModuleNoBody &module) {} + virtual void visit (HIR::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (HIR::UseTreeGlob &use_tree) {} + virtual void visit (HIR::UseTreeList &use_tree) {} + virtual void visit (HIR::UseTreeRebind &use_tree) {} + virtual void visit (HIR::UseDeclaration &use_decl) {} + virtual void visit (HIR::Function &function) {} + virtual void visit (HIR::TypeAlias &type_alias) {} + virtual void visit (HIR::StructStruct &struct_item) {} + virtual void visit (HIR::TupleStruct &tuple_struct) {} + virtual void visit (HIR::EnumItem &item) {} + virtual void visit (HIR::EnumItemTuple &item) {} + virtual void visit (HIR::EnumItemStruct &item) {} + virtual void visit (HIR::EnumItemDiscriminant &item) {} + virtual void visit (HIR::Enum &enum_item) {} + virtual void visit (HIR::Union &union_item) {} + virtual void visit (HIR::ConstantItem &const_item) {} + virtual void visit (HIR::StaticItem &static_item) {} + virtual void visit (HIR::TraitItemFunc &item) {} + virtual void visit (HIR::TraitItemMethod &item) {} + virtual void visit (HIR::TraitItemConst &item) {} + virtual void visit (HIR::TraitItemType &item) {} + virtual void visit (HIR::Trait &trait) {} + virtual void visit (HIR::InherentImpl &impl) {} + virtual void visit (HIR::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (HIR::ExternalStaticItem &item) {} + virtual void visit (HIR::ExternalFunctionItem &item) {} + virtual void visit (HIR::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (HIR::MacroMatchFragment &match) {} + virtual void visit (HIR::MacroMatchRepetition &match) {} + virtual void visit (HIR::MacroMatcher &matcher) {} + virtual void visit (HIR::MacroRulesDefinition &rules_def) {} + virtual void visit (HIR::MacroInvocation ¯o_invoc) {} + virtual void visit (HIR::MetaItemPath &meta_item) {} + virtual void visit (HIR::MetaItemSeq &meta_item) {} + virtual void visit (HIR::MetaWord &meta_item) {} + virtual void visit (HIR::MetaNameValueStr &meta_item) {} + virtual void visit (HIR::MetaListPaths &meta_item) {} + virtual void visit (HIR::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (HIR::LiteralPattern &pattern) {} + virtual void visit (HIR::IdentifierPattern &pattern) {} + virtual void visit (HIR::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (HIR::RangePatternBoundLiteral &bound) {} + virtual void visit (HIR::RangePatternBoundPath &bound) {} + virtual void visit (HIR::RangePatternBoundQualPath &bound) {} + virtual void visit (HIR::RangePattern &pattern) {} + virtual void visit (HIR::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (HIR::StructPatternFieldTuplePat &field) {} + virtual void visit (HIR::StructPatternFieldIdentPat &field) {} + virtual void visit (HIR::StructPatternFieldIdent &field) {} + virtual void visit (HIR::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (HIR::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (HIR::TupleStructItemsRange &tuple_items) {} + virtual void visit (HIR::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (HIR::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (HIR::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (HIR::TuplePattern &pattern) {} + virtual void visit (HIR::GroupedPattern &pattern) {} + virtual void visit (HIR::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (HIR::EmptyStmt &stmt) {} + virtual void visit (HIR::LetStmt &stmt) {} + virtual void visit (HIR::ExprStmtWithoutBlock &stmt) {} + virtual void visit (HIR::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (HIR::TraitBound &bound) {} + virtual void visit (HIR::ImplTraitType &type) {} + virtual void visit (HIR::TraitObjectType &type) {} + virtual void visit (HIR::ParenthesisedType &type) {} + virtual void visit (HIR::ImplTraitTypeOneBound &type) {} + virtual void visit (HIR::TraitObjectTypeOneBound &type) {} + virtual void visit (HIR::TupleType &type) {} + virtual void visit (HIR::NeverType &type) {} + virtual void visit (HIR::RawPointerType &type) {} + virtual void visit (HIR::ReferenceType &type) {} + virtual void visit (HIR::ArrayType &type) {} + virtual void visit (HIR::SliceType &type) {} + virtual void visit (HIR::InferredType &type) {} + virtual void visit (HIR::BareFunctionType &type) {} + +protected: + TypeCheckBase () + : mappings (Analysis::Mappings::get ()), resolver (Resolver::get ()), + context (TypeCheckContext::get ()) + {} + + Analysis::Mappings *mappings; + Resolver *resolver; + TypeCheckContext *context; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_HIR_TYPE_CHECK_BASE diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h new file mode 100644 index 0000000..2e715e9 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.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 +// . + +#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; + } + + // 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; + } + + // 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: + infered = new TyTy::IntType (expr.get_mappings ().get_hirid (), + TyTy::IntType::IntKind::I32); + break; + + case HIR::Literal::LitType::BOOL: + infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ()); + 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..29d6db6 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -0,0 +1,90 @@ +// 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 +// . + +#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..39c48f0 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -0,0 +1,86 @@ +// 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 +// . + +#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::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..c15aaef --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -0,0 +1,63 @@ +// 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 +// . + +#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 params; + for (auto ¶m : function.function_params) + params.push_back (TypeCheckType::Resolve (param.type.get ())); + + 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..d8721a3 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -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 +// . + +#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; + } + + 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 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 +// . + +#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..5a8abe1 --- /dev/null +++ b/gcc/rust/typecheck/rust-hir-type-check.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 +// . + +#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 (); + + 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 node_id_refs; + std::map resolved; + std::vector > builtins; + std::vector 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..195291e --- /dev/null +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -0,0 +1,104 @@ +// 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 +// . + +#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 () {} + +void +TypeCheckContext::insert_builtin (HirId id, NodeId ref, TyTy::TyBase *type) +{ + printf ("inserting builtin: hir %u node %u -> %s\n", id, ref, + type->as_string ().c_str ()); + node_id_refs[ref] = id; + resolved[id] = type; + builtins.push_back (std::unique_ptr (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 +// . + +#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..375d909 --- /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 +// . + +#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) + { + other->accept_vis (*this); + return resolved; + } + +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 +// . + +#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..2124408 --- /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 +// . + +#include "rust-tyty.h" +#include "rust-tyty-visitor.h" +#include "rust-tyty-call.h" +#include "rust-hir-type-check-expr.h" +#include "rust-tyty-rules.h" + +namespace Rust { +namespace TyTy { + +void +UnitType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +UnitType::as_string () const +{ + return "()"; +} + +TyBase * +UnitType::combine (TyBase *other) +{ + UnitRules r (this); + return r.combine (other); +} + +void +InferType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +InferType::as_string () const +{ + return "[_]"; +} + +TyBase * +InferType::combine (TyBase *other) +{ + InferRules r (this); + return r.combine (other); +} + +void +FnType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +FnType::as_string () const +{ + std::string params_str = ""; + for (auto ¶m : params) + { + params_str += param->as_string (); + params_str += ","; + } + + std::string ret_str = type->as_string (); + return "fn (" + params_str + ") -> " + ret_str; +} + +TyBase * +FnType::combine (TyBase *other) +{ + FnRules r (this); + return r.combine (other); +} + +void +ParamType::accept_vis (TyVisitor &vis) +{ + vis.visit (*this); +} + +std::string +ParamType::as_string () const +{ + return "(" + 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..688643c --- /dev/null +++ b/gcc/rust/typecheck/rust-tyty.h @@ -0,0 +1,208 @@ +// 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 +// . + +#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 bool is_unit () const { return false; } + + virtual std::string as_string () const = 0; + + virtual TyBase *combine (TyBase *other) = 0; + +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 FnType : public TyBase +{ +public: + FnType (HirId ref, std::vector 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 (); } + + TyBase *param_at (size_t idx) { return params[idx]; } + + TyBase *get_return_type () { return type; } + +private: + std::vector params; + TyBase *type; +}; + +class ParamType : public TyBase +{ +public: + ParamType (HirId ref, TyBase *type) + : TyBase (ref, TypeKind::PARAM), type (type) + {} + + void accept_vis (TyVisitor &vis) override; + + std::string as_string () const override; + + TyBase *combine (TyBase *other) override; + +private: + 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 index 094d0e3..70c59f3 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -133,6 +133,8 @@ Mappings::get_current_crate () hirIdIter[currentCrateNum] = UNKNOWN_HIRID; nodeIdIter[currentCrateNum] = UNKNOWN_NODEID; localIdIter[currentCrateNum] = UNKNOWN_LOCAL_DEFID; + nodeIdToHirMappings[currentCrateNum] = {}; + locations[currentCrateNum] = {}; } return currentCrateNum; @@ -157,7 +159,7 @@ Mappings::get_next_hir_id (CrateNum crateNum) auto id = it->second + 1; hirIdIter[crateNum] = id; - return id++; + return id; } LocalDefId @@ -238,6 +240,7 @@ 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 * @@ -260,6 +263,8 @@ 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 * @@ -277,6 +282,29 @@ Mappings::lookup_hir_expr (CrateNum crateNum, HirId id) } 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_local_defid_mapping (CrateNum crateNum, LocalDefId id, HIR::Item *item) { @@ -314,5 +342,40 @@ Mappings::walk_local_defids_for_crate (CrateNum crateNum, } } +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; +} + } // namespace Analysis } // namespace Rust diff --git a/gcc/rust/util/rust-hir-map.h b/gcc/rust/util/rust-hir-map.h index 8929ca4..7fc8777 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -20,6 +20,7 @@ #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" @@ -40,11 +41,11 @@ typedef uint64_t DefId; #define DEF_ID_CRATE_MASK 0xFFFFFFFF00000000 #define DEF_ID_LOCAL_DEF_MASK 0x00000000FFFFFFFF -#define UNKNOWN_CREATENUM ((uint32_t) (-1)) -#define UNKNOWN_NODEID ((uint32_t) (-1)) -#define UNKNOWN_HIRID ((uint32_t) (-1)) -#define UNKNOWN_LOCAL_DEFID ((uint32_t) (-1)) -#define UNKNOWN_DEFID ((uint64_t) (-1)) +#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 { @@ -86,7 +87,10 @@ public: 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); @@ -108,9 +112,21 @@ public: 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 walk_local_defids_for_crate (CrateNum crateNum, std::function 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); + } + private: Mappings (); @@ -127,8 +143,12 @@ private: std::map defIdMappings; std::map > localDefIdMappings; std::map > hirItemMappings; + std::map > hirTypeMappings; std::map > hirExprMappings; + // location info + std::map > locations; + // reverse mappings std::map > nodeIdToHirMappings; }; diff --git a/gcc/rust/util/rust-inference-var.h b/gcc/rust/util/rust-inference-var.h deleted file mode 100644 index 87decd5..0000000 --- a/gcc/rust/util/rust-inference-var.h +++ /dev/null @@ -1,112 +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 -// . - -#ifndef RUST_HIR_INFERENCE_VAR -#define RUST_HIR_INFERENCE_VAR - -#include "rust-system.h" -#include "rust-hir-full-decls.h" - -namespace Rust { -namespace HIR { - -class GeneralInferenceVariable; -class IntegralInferenceVariable; -class FloatInferenceVariable; -class InferenceVarVisitor -{ -public: - virtual void visit (GeneralInferenceVariable &v) {} - virtual void visit (IntegralInferenceVariable &v) {} - virtual void visit (FloatInferenceVariable &v) {} -}; - -// Base -class InferenceVariable -{ -public: - virtual ~InferenceVariable () {} - - virtual std::string as_string () const = 0; - - HIR::Type *get_type () { return resolved; } - - void set_type (HIR::Type *type) { resolved = type; } - - bool was_resolved () { return resolved != nullptr; } - - virtual void accept_vis (InferenceVarVisitor &vis) = 0; - -protected: - InferenceVariable () : resolved (nullptr) {} - - HIR::Type *resolved; -}; - -class GeneralInferenceVariable : public InferenceVariable -{ -public: - GeneralInferenceVariable () : InferenceVariable () {} - - void accept_vis (InferenceVarVisitor &vis) { vis.visit (*this); }; - - std::string as_string () const override - { - if (resolved) - return resolved->as_string (); - - return "[G::?T]"; - } -}; - -class IntegralInferenceVariable : public InferenceVariable -{ -public: - IntegralInferenceVariable () : InferenceVariable () {} - - void accept_vis (InferenceVarVisitor &vis) { vis.visit (*this); }; - - std::string as_string () const override - { - if (resolved) - return resolved->as_string (); - - return "[I::?T]"; - } -}; - -class FloatInferenceVariable : public InferenceVariable -{ -public: - FloatInferenceVariable () : InferenceVariable () {} - - void accept_vis (InferenceVarVisitor &vis) { vis.visit (*this); }; - - std::string as_string () const override - { - if (resolved) - return resolved->as_string (); - - return "[F::?T]"; - } -}; - -} // namespace HIR -} // namespace Rust - -#endif // RUST_HIR_INFERENCE_VAR -- cgit v1.1 From a621e19365473b477d121c28a057cc25d3951c76 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 15 Dec 2020 17:26:07 +0000 Subject: Remove old analysis framework and strip the AST->GIMPLE pass this needs to use the new name and type resolution pass contexts. --- gcc/rust/Make-lang.in | 8 - gcc/rust/analysis/rust-name-resolution.cc | 657 ------------- gcc/rust/analysis/rust-name-resolution.h | 232 ----- gcc/rust/analysis/rust-resolution.cc | 867 ----------------- gcc/rust/analysis/rust-resolution.h | 51 - gcc/rust/analysis/rust-scan.cc | 593 ------------ gcc/rust/analysis/rust-scan.h | 233 ----- gcc/rust/analysis/rust-type-resolution.cc | 1348 -------------------------- gcc/rust/analysis/rust-type-resolution.h | 334 ------- gcc/rust/analysis/rust-type-visitor.h | 261 ----- gcc/rust/backend/rust-compile.cc | 1507 +---------------------------- gcc/rust/backend/rust-compile.h | 306 ++---- gcc/rust/rust-session-manager.cc | 17 +- gcc/rust/util/scope.h | 78 -- 14 files changed, 103 insertions(+), 6389 deletions(-) delete mode 100644 gcc/rust/analysis/rust-name-resolution.cc delete mode 100644 gcc/rust/analysis/rust-name-resolution.h delete mode 100644 gcc/rust/analysis/rust-resolution.cc delete mode 100644 gcc/rust/analysis/rust-resolution.h delete mode 100644 gcc/rust/analysis/rust-scan.cc delete mode 100644 gcc/rust/analysis/rust-scan.h delete mode 100644 gcc/rust/analysis/rust-type-resolution.cc delete mode 100644 gcc/rust/analysis/rust-type-resolution.h delete mode 100644 gcc/rust/analysis/rust-type-visitor.h delete mode 100644 gcc/rust/util/scope.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 96457ed..56f308e 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -69,9 +69,6 @@ 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-macro-expand.o \ rust/rust-hir-full-test.o \ @@ -261,11 +258,6 @@ rust/%.o: rust/ast/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< $(POSTCOMPILE) -# build rust/analysis files in rust folder -rust/%.o: rust/analysis/%.cc - $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< - $(POSTCOMPILE) - # build rust/backend files in rust folder rust/%.o: rust/backend/%.cc $(COMPILE) $(RUST_CXXFLAGS) $(RUST_INCLUDES) $< diff --git a/gcc/rust/analysis/rust-name-resolution.cc b/gcc/rust/analysis/rust-name-resolution.cc deleted file mode 100644 index 28a4af8..0000000 --- a/gcc/rust/analysis/rust-name-resolution.cc +++ /dev/null @@ -1,657 +0,0 @@ -#include "rust-name-resolution.h" -#include "rust-diagnostics.h" - -/* - * The principles of name resolution: - * 1. If a name resolves to a binding then it should always resolve to that - * binding, and if resolving a name produces an error, it should always produce - * an error. - * 2. Avoid errors due to the resolver being stuck. - * 3. Names should be able to be used before they are declared, but the order of - * declarations should be irrelevant. - * 4. Macros should be hygiene and manually expandable. - * 5. Glob imports should be manually expandable. - */ - -/* The algorithm of name resolution - * 1. When encouter items which bind a name, add the name to the binding table. - * 2. When we find an import which can't be resolved, we add it to a work list. - * 3. When we find a glob import, we have to record a 'back link', so that when - * a public name is added for the supplying module, we can add it for the - * importing module. - * 4. Loop over the work list and try to lookup names. - * a. If a name has exactly one best binding then we use it (and record the - * binding on a list of resolved names). - * b. If there are zero then we put it back on the work list. - * c. If there is more than one binding, then we record an ambiguity error. - * d. When the work list no longer changes, then we are done. - * e. If the work list is empty, then expansion/import resolution succeeded. - * Otherwise there are names not found, or ambiguous names, then failed. - * 5. When looking up names, we record the resolutions in the binding table. - * a. If the name a glob import, we add bindings for every accessible name - * currently known. - * 6. To expand a macro, we try to resolve the macro's name. - * a. If that fails, we put it on the work list. - * Otherwise, we expand that macro by parsing the arguments, - * pattern matching, and doing hygienic expansion. - * b. We then parse the generated code in the same way as we parsed the - * original program. We add new names to the binding table, and expand any - * new macro uses. - * 7. If we add names for a module which has back links, we must follow them and - * add these names to the importing module (if they are accessible). - */ - -namespace Rust { -namespace Analysis { - -NameResolution::NameResolution (AST::Crate &crate, TopLevelScan &toplevel) - : Resolution (crate, toplevel), is_work_list_changed_ (false) - -{} - -NameResolution::~NameResolution () {} - -bool -NameResolution::Resolve (AST::Crate &crate, TopLevelScan &toplevel) -{ - NameResolution resolver (crate, toplevel); - return resolver.go (); -} - -void -NameResolution::process_work_list () -{} - -void -NameResolution::expand_macros () -{} - -bool -NameResolution::go () -{ - bool ret = true; - - do - { - for (auto &item : crate.items) - { - item->accept_vis (*this); - } - } - while (is_work_list_changed ()); - - ret = work_list_.empty (); - for (auto &item : work_list_) - { - std::cout << "Resolution error: " << item.as_string () << std::endl; - } - - return ret; -} - -void -NameResolution::visit (AST::Token &tok) -{} - -void -NameResolution::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -NameResolution::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -NameResolution::visit (AST::IdentifierExpr &ident_expr) -{ - do - { - process_work_list (); - } - while (is_work_list_changed ()); - expand_macros (); -} - -void -NameResolution::visit (AST::Lifetime &lifetime) -{} - -void -NameResolution::visit (AST::LifetimeParam &lifetime_param) -{} - -void -NameResolution::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -NameResolution::visit (AST::PathInExpression &path) -{} - -void -NameResolution::visit (AST::TypePathSegment &segment) -{} -void -NameResolution::visit (AST::TypePathSegmentGeneric &segment) -{} - -void -NameResolution::visit (AST::TypePathSegmentFunction &segment) -{} - -void -NameResolution::visit (AST::TypePath &path) -{} - -void -NameResolution::visit (AST::QualifiedPathInExpression &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -NameResolution::visit (AST::QualifiedPathInType &path) -{} - -// rust-expr.h -void -NameResolution::visit (AST::LiteralExpr &expr) -{} - -void -NameResolution::visit (AST::AttrInputLiteral &attr_input) -{} - -void -NameResolution::visit (AST::MetaItemLitExpr &meta_item) -{} - -void -NameResolution::visit (AST::MetaItemPathLit &meta_item) -{} - -void -NameResolution::visit (AST::BorrowExpr &expr) -{} -void -NameResolution::visit (AST::DereferenceExpr &expr) -{} -void -NameResolution::visit (AST::ErrorPropagationExpr &expr) -{} -void -NameResolution::visit (AST::NegationExpr &expr) -{} - -void -NameResolution::visit (AST::ArithmeticOrLogicalExpr &expr) -{} - -void -NameResolution::visit (AST::ComparisonExpr &expr) -{} - -void -NameResolution::visit (AST::LazyBooleanExpr &expr) -{} - -void -NameResolution::visit (AST::TypeCastExpr &expr) -{} - -void -NameResolution::visit (AST::AssignmentExpr &expr) -{} - -void -NameResolution::visit (AST::CompoundAssignmentExpr &expr) -{} - -void -NameResolution::visit (AST::GroupedExpr &expr) -{} -// void NameResolution::visit(ArrayElems& elems) {} -void -NameResolution::visit (AST::ArrayElemsValues &elems) -{} -void -NameResolution::visit (AST::ArrayElemsCopied &elems) -{} -void -NameResolution::visit (AST::ArrayExpr &expr) -{} -void -NameResolution::visit (AST::ArrayIndexExpr &expr) -{} -void -NameResolution::visit (AST::TupleExpr &expr) -{} -void -NameResolution::visit (AST::TupleIndexExpr &expr) -{} -void -NameResolution::visit (AST::StructExprStruct &expr) -{} -// void NameResolution::visit(StructExprField& field) {} -void -NameResolution::visit (AST::StructExprFieldIdentifier &field) -{} -void -NameResolution::visit (AST::StructExprFieldIdentifierValue &field) -{} -void -NameResolution::visit (AST::StructExprFieldIndexValue &field) -{} -void -NameResolution::visit (AST::StructExprStructFields &expr) -{} -void -NameResolution::visit (AST::StructExprStructBase &expr) -{} -void -NameResolution::visit (AST::StructExprTuple &expr) -{} -void -NameResolution::visit (AST::StructExprUnit &expr) -{} -// void NameResolution::visit(EnumExprField& field) {} -void -NameResolution::visit (AST::EnumExprFieldIdentifier &field) -{} -void -NameResolution::visit (AST::EnumExprFieldIdentifierValue &field) -{} -void -NameResolution::visit (AST::EnumExprFieldIndexValue &field) -{} -void -NameResolution::visit (AST::EnumExprStruct &expr) -{} -void -NameResolution::visit (AST::EnumExprTuple &expr) -{} -void -NameResolution::visit (AST::EnumExprFieldless &expr) -{} - -void -NameResolution::visit (AST::CallExpr &expr) -{} - -void -NameResolution::visit (AST::MethodCallExpr &expr) -{} -void -NameResolution::visit (AST::FieldAccessExpr &expr) -{} -void -NameResolution::visit (AST::ClosureExprInner &expr) -{} -void -NameResolution::visit (AST::BlockExpr &expr) -{} -void -NameResolution::visit (AST::ClosureExprInnerTyped &expr) -{} -void -NameResolution::visit (AST::ContinueExpr &expr) -{} -void -NameResolution::visit (AST::BreakExpr &expr) -{} -void -NameResolution::visit (AST::RangeFromToExpr &expr) -{} -void -NameResolution::visit (AST::RangeFromExpr &expr) -{} -void -NameResolution::visit (AST::RangeToExpr &expr) -{} -void -NameResolution::visit (AST::RangeFullExpr &expr) -{} -void -NameResolution::visit (AST::RangeFromToInclExpr &expr) -{} -void -NameResolution::visit (AST::RangeToInclExpr &expr) -{} -void -NameResolution::visit (AST::ReturnExpr &expr) -{} -void -NameResolution::visit (AST::UnsafeBlockExpr &expr) -{} -void -NameResolution::visit (AST::LoopExpr &expr) -{} -void -NameResolution::visit (AST::WhileLoopExpr &expr) -{} -void -NameResolution::visit (AST::WhileLetLoopExpr &expr) -{} -void -NameResolution::visit (AST::ForLoopExpr &expr) -{} -void -NameResolution::visit (AST::IfExpr &expr) -{} -void -NameResolution::visit (AST::IfExprConseqElse &expr) -{} -void -NameResolution::visit (AST::IfExprConseqIf &expr) -{} -void -NameResolution::visit (AST::IfExprConseqIfLet &expr) -{} -void -NameResolution::visit (AST::IfLetExpr &expr) -{} -void -NameResolution::visit (AST::IfLetExprConseqElse &expr) -{} -void -NameResolution::visit (AST::IfLetExprConseqIf &expr) -{} -void -NameResolution::visit (AST::IfLetExprConseqIfLet &expr) -{} -// void NameResolution::visit(MatchCase& match_case) {} -/*void -NameResolution::visit (AST::MatchCaseBlockExpr &match_case) -{}*/ -/*void -NameResolution::visit (AST::MatchCaseExpr &match_case) -{}*/ -void -NameResolution::visit (AST::MatchExpr &expr) -{} -void -NameResolution::visit (AST::AwaitExpr &expr) -{} -void -NameResolution::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -NameResolution::visit (AST::TypeParam ¶m) -{} -// void NameResolution::visit(WhereClauseItem& item) {} -void -NameResolution::visit (AST::LifetimeWhereClauseItem &item) -{} -void -NameResolution::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -NameResolution::visit (AST::Method &method) -{} -void -NameResolution::visit (AST::ModuleBodied &module) -{} -void -NameResolution::visit (AST::ModuleNoBody &module) -{} -void -NameResolution::visit (AST::ExternCrate &crate) -{} -// void NameResolution::visit(UseTree& use_tree) {} -void -NameResolution::visit (AST::UseTreeGlob &use_tree) -{} -void -NameResolution::visit (AST::UseTreeList &use_tree) -{} -void -NameResolution::visit (AST::UseTreeRebind &use_tree) -{} -void -NameResolution::visit (AST::UseDeclaration &use_decl) -{} - -void -NameResolution::visit (AST::Function &function) -{} - -void -NameResolution::visit (AST::TypeAlias &type_alias) -{} -void -NameResolution::visit (AST::StructStruct &struct_item) -{} -void -NameResolution::visit (AST::TupleStruct &tuple_struct) -{} -void -NameResolution::visit (AST::EnumItem &item) -{} -void -NameResolution::visit (AST::EnumItemTuple &item) -{} -void -NameResolution::visit (AST::EnumItemStruct &item) -{} -void -NameResolution::visit (AST::EnumItemDiscriminant &item) -{} -void -NameResolution::visit (AST::Enum &enum_item) -{} -void -NameResolution::visit (AST::Union &union_item) -{} - -void -NameResolution::visit (AST::ConstantItem &const_item) -{} - -void -NameResolution::visit (AST::StaticItem &static_item) -{} -void -NameResolution::visit (AST::TraitItemFunc &item) -{} -void -NameResolution::visit (AST::TraitItemMethod &item) -{} -void -NameResolution::visit (AST::TraitItemConst &item) -{} -void -NameResolution::visit (AST::TraitItemType &item) -{} -void -NameResolution::visit (AST::Trait &trait) -{} -void -NameResolution::visit (AST::InherentImpl &impl) -{} -void -NameResolution::visit (AST::TraitImpl &impl) -{} -// void NameResolution::visit(ExternalItem& item) {} -void -NameResolution::visit (AST::ExternalStaticItem &item) -{} -void -NameResolution::visit (AST::ExternalFunctionItem &item) -{} -void -NameResolution::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -NameResolution::visit (AST::MacroMatchFragment &match) -{} -void -NameResolution::visit (AST::MacroMatchRepetition &match) -{} -void -NameResolution::visit (AST::MacroMatcher &matcher) -{} - -void -NameResolution::visit (AST::MacroRulesDefinition &rules_def) -{} - -void -NameResolution::visit (AST::MacroInvocation ¯o_invoc) -{} -void -NameResolution::visit (AST::MetaItemPath &meta_item) -{} -void -NameResolution::visit (AST::MetaItemSeq &meta_item) -{} -void -NameResolution::visit (AST::MetaWord &meta_item) -{} -void -NameResolution::visit (AST::MetaNameValueStr &meta_item) -{} -void -NameResolution::visit (AST::MetaListPaths &meta_item) -{} -void -NameResolution::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -NameResolution::visit (AST::LiteralPattern &pattern) -{} - -void -NameResolution::visit (AST::IdentifierPattern &pattern) -{} - -void -NameResolution::visit (AST::WildcardPattern &pattern) -{} -// void NameResolution::visit(RangePatternBound& bound) {} -void -NameResolution::visit (AST::RangePatternBoundLiteral &bound) -{} -void -NameResolution::visit (AST::RangePatternBoundPath &bound) -{} -void -NameResolution::visit (AST::RangePatternBoundQualPath &bound) -{} -void -NameResolution::visit (AST::RangePattern &pattern) -{} -void -NameResolution::visit (AST::ReferencePattern &pattern) -{} -// void NameResolution::visit(StructPatternField& field) {} -void -NameResolution::visit (AST::StructPatternFieldTuplePat &field) -{} -void -NameResolution::visit (AST::StructPatternFieldIdentPat &field) -{} -void -NameResolution::visit (AST::StructPatternFieldIdent &field) -{} -void -NameResolution::visit (AST::StructPattern &pattern) -{} -// void NameResolution::visit(TupleStructItems& tuple_items) {} -void -NameResolution::visit (AST::TupleStructItemsNoRange &tuple_items) -{} -void -NameResolution::visit (AST::TupleStructItemsRange &tuple_items) -{} -void -NameResolution::visit (AST::TupleStructPattern &pattern) -{} -// void NameResolution::visit(TuplePatternItems& tuple_items) {} -void -NameResolution::visit (AST::TuplePatternItemsMultiple &tuple_items) -{} -void -NameResolution::visit (AST::TuplePatternItemsRanged &tuple_items) -{} -void -NameResolution::visit (AST::TuplePattern &pattern) -{} -void -NameResolution::visit (AST::GroupedPattern &pattern) -{} -void -NameResolution::visit (AST::SlicePattern &pattern) -{} - -// rust-stmt.h -void -NameResolution::visit (AST::EmptyStmt &stmt) -{} - -void -NameResolution::visit (AST::LetStmt &stmt) -{} - -void -NameResolution::visit (AST::ExprStmtWithoutBlock &stmt) -{} - -void -NameResolution::visit (AST::ExprStmtWithBlock &stmt) -{} - -// rust-type.h -void -NameResolution::visit (AST::TraitBound &bound) -{} - -void -NameResolution::visit (AST::ImplTraitType &type) -{} - -void -NameResolution::visit (AST::TraitObjectType &type) -{} -void -NameResolution::visit (AST::ParenthesisedType &type) -{} -void -NameResolution::visit (AST::ImplTraitTypeOneBound &type) -{} -void -NameResolution::visit (AST::TraitObjectTypeOneBound &type) -{} -void -NameResolution::visit (AST::TupleType &type) -{} -void -NameResolution::visit (AST::NeverType &type) -{} -void -NameResolution::visit (AST::RawPointerType &type) -{} -void -NameResolution::visit (AST::ReferenceType &type) -{} -void -NameResolution::visit (AST::ArrayType &type) -{} -void -NameResolution::visit (AST::SliceType &type) -{} -void -NameResolution::visit (AST::InferredType &type) -{} -void -NameResolution::visit (AST::BareFunctionType &type) -{} - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-name-resolution.h b/gcc/rust/analysis/rust-name-resolution.h deleted file mode 100644 index b3bc780..0000000 --- a/gcc/rust/analysis/rust-name-resolution.h +++ /dev/null @@ -1,232 +0,0 @@ -#pragma once - -#include "rust-resolution.h" -#include - -namespace Rust { -namespace Analysis { - -class NameResolution : public Resolution -{ -public: - ~NameResolution (); - static bool Resolve (AST::Crate &crate, TopLevelScan &toplevel); - - // visitor impl - // rust-ast.h - // void visit(AttrInput& attr_input); - // void visit(TokenTree& token_tree); - // void visit(MacroMatch& macro_match); - void visit (AST::Token &tok) override; - void visit (AST::DelimTokenTree &delim_tok_tree) override; - void visit (AST::AttrInputMetaItemContainer &input) override; - // void visit(MetaItem& meta_item) override; - // void vsit(Stmt& stmt) override; - // void visit(Expr& expr) override; - void visit (AST::IdentifierExpr &ident_expr) override; - // void visit(Pattern& pattern) override; - // void visit(Type& type) override; - // void visit(TypeParamBound& type_param_bound) override; - void visit (AST::Lifetime &lifetime) override; - // void visit(GenericParam& generic_param) override; - void visit (AST::LifetimeParam &lifetime_param) override; - // void visit(TraitItem& trait_item) override; - // void visit(InherentImplItem& inherent_impl_item) override; - // void visit(TraitImplItem& trait_impl_item) override; - void visit (AST::MacroInvocationSemi ¯o) override; - - // rust-path.h - void visit (AST::PathInExpression &path) override; - void visit (AST::TypePathSegment &segment) override; - void visit (AST::TypePathSegmentGeneric &segment) override; - void visit (AST::TypePathSegmentFunction &segment) override; - void visit (AST::TypePath &path) override; - void visit (AST::QualifiedPathInExpression &path) override; - void visit (AST::QualifiedPathInType &path) override; - - // rust-expr.h - void visit (AST::LiteralExpr &expr) override; - void visit (AST::AttrInputLiteral &attr_input) override; - void visit (AST::MetaItemLitExpr &meta_item) override; - void visit (AST::MetaItemPathLit &meta_item) override; - void visit (AST::BorrowExpr &expr) override; - void visit (AST::DereferenceExpr &expr) override; - void visit (AST::ErrorPropagationExpr &expr) override; - void visit (AST::NegationExpr &expr) override; - void visit (AST::ArithmeticOrLogicalExpr &expr) override; - void visit (AST::ComparisonExpr &expr) override; - void visit (AST::LazyBooleanExpr &expr) override; - void visit (AST::TypeCastExpr &expr) override; - void visit (AST::AssignmentExpr &expr) override; - void visit (AST::CompoundAssignmentExpr &expr) override; - void visit (AST::GroupedExpr &expr) override; - // void visit(ArrayElems& elems) override; - void visit (AST::ArrayElemsValues &elems) override; - void visit (AST::ArrayElemsCopied &elems) override; - void visit (AST::ArrayExpr &expr) override; - void visit (AST::ArrayIndexExpr &expr) override; - void visit (AST::TupleExpr &expr) override; - void visit (AST::TupleIndexExpr &expr) override; - void visit (AST::StructExprStruct &expr) override; - // void visit(StructExprField& field) override; - void visit (AST::StructExprFieldIdentifier &field) override; - void visit (AST::StructExprFieldIdentifierValue &field) override; - void visit (AST::StructExprFieldIndexValue &field) override; - void visit (AST::StructExprStructFields &expr) override; - void visit (AST::StructExprStructBase &expr) override; - void visit (AST::StructExprTuple &expr) override; - void visit (AST::StructExprUnit &expr) override; - // void visit(EnumExprField& field) override; - void visit (AST::EnumExprFieldIdentifier &field) override; - void visit (AST::EnumExprFieldIdentifierValue &field) override; - void visit (AST::EnumExprFieldIndexValue &field) override; - void visit (AST::EnumExprStruct &expr) override; - void visit (AST::EnumExprTuple &expr) override; - void visit (AST::EnumExprFieldless &expr) override; - void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; - void visit (AST::FieldAccessExpr &expr) override; - void visit (AST::ClosureExprInner &expr) override; - void visit (AST::BlockExpr &expr) override; - void visit (AST::ClosureExprInnerTyped &expr) override; - void visit (AST::ContinueExpr &expr) override; - void visit (AST::BreakExpr &expr) override; - void visit (AST::RangeFromToExpr &expr) override; - void visit (AST::RangeFromExpr &expr) override; - void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &expr) override; - void visit (AST::RangeFromToInclExpr &expr) override; - void visit (AST::RangeToInclExpr &expr) override; - void visit (AST::ReturnExpr &expr) override; - void visit (AST::UnsafeBlockExpr &expr) override; - void visit (AST::LoopExpr &expr) override; - void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::WhileLetLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; - void visit (AST::IfExpr &expr) override; - void visit (AST::IfExprConseqElse &expr) override; - void visit (AST::IfExprConseqIf &expr) override; - void visit (AST::IfExprConseqIfLet &expr) override; - void visit (AST::IfLetExpr &expr) override; - void visit (AST::IfLetExprConseqElse &expr) override; - void visit (AST::IfLetExprConseqIf &expr) override; - void visit (AST::IfLetExprConseqIfLet &expr) override; - // void visit(MatchCase& match_case) override; - // void visit (AST::MatchCaseBlockExpr &match_case) override; - // void visit (AST::MatchCaseExpr &match_case) override; - void visit (AST::MatchExpr &expr) override; - void visit (AST::AwaitExpr &expr) override; - void visit (AST::AsyncBlockExpr &expr) override; - - // rust-item.h - void visit (AST::TypeParam ¶m) override; - // void visit(WhereClauseItem& item) override; - void visit (AST::LifetimeWhereClauseItem &item) override; - void visit (AST::TypeBoundWhereClauseItem &item) override; - void visit (AST::Method &method) override; - void visit (AST::ModuleBodied &module) override; - void visit (AST::ModuleNoBody &module) override; - void visit (AST::ExternCrate &crate) override; - // void visit(UseTree& use_tree) override; - void visit (AST::UseTreeGlob &use_tree) override; - void visit (AST::UseTreeList &use_tree) override; - void visit (AST::UseTreeRebind &use_tree) override; - void visit (AST::UseDeclaration &use_decl) override; - void visit (AST::Function &function) override; - void visit (AST::TypeAlias &type_alias) override; - void visit (AST::StructStruct &struct_item) override; - void visit (AST::TupleStruct &tuple_struct) override; - void visit (AST::EnumItem &item) override; - void visit (AST::EnumItemTuple &item) override; - void visit (AST::EnumItemStruct &item) override; - void visit (AST::EnumItemDiscriminant &item) override; - void visit (AST::Enum &enum_item) override; - void visit (AST::Union &union_item) override; - void visit (AST::ConstantItem &const_item) override; - void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemFunc &item) override; - void visit (AST::TraitItemMethod &item) override; - void visit (AST::TraitItemConst &item) override; - void visit (AST::TraitItemType &item) override; - void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl) override; - void visit (AST::TraitImpl &impl) override; - // void visit(ExternalItem& item) override; - void visit (AST::ExternalStaticItem &item) override; - void visit (AST::ExternalFunctionItem &item) override; - void visit (AST::ExternBlock &block) override; - - // rust-macro.h - void visit (AST::MacroMatchFragment &match) override; - void visit (AST::MacroMatchRepetition &match) override; - void visit (AST::MacroMatcher &matcher) override; - void visit (AST::MacroRulesDefinition &rules_def) override; - void visit (AST::MacroInvocation ¯o_invoc) override; - void visit (AST::MetaItemPath &meta_item) override; - void visit (AST::MetaItemSeq &meta_item) override; - void visit (AST::MetaWord &meta_item) override; - void visit (AST::MetaNameValueStr &meta_item) override; - void visit (AST::MetaListPaths &meta_item) override; - void visit (AST::MetaListNameValueStr &meta_item) override; - - // rust-pattern.h - void visit (AST::LiteralPattern &pattern) override; - void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::WildcardPattern &pattern) override; - // void visit(RangePatternBound& bound) override; - void visit (AST::RangePatternBoundLiteral &bound) override; - void visit (AST::RangePatternBoundPath &bound) override; - void visit (AST::RangePatternBoundQualPath &bound) override; - void visit (AST::RangePattern &pattern) override; - void visit (AST::ReferencePattern &pattern) override; - // void visit(StructPatternField& field) override; - void visit (AST::StructPatternFieldTuplePat &field) override; - void visit (AST::StructPatternFieldIdentPat &field) override; - void visit (AST::StructPatternFieldIdent &field) override; - void visit (AST::StructPattern &pattern) override; - // void visit(TupleStructItems& tuple_items) override; - void visit (AST::TupleStructItemsNoRange &tuple_items) override; - void visit (AST::TupleStructItemsRange &tuple_items) override; - void visit (AST::TupleStructPattern &pattern) override; - // void visit(TuplePatternItems& tuple_items) override; - void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - void visit (AST::TuplePatternItemsRanged &tuple_items) override; - void visit (AST::TuplePattern &pattern) override; - void visit (AST::GroupedPattern &pattern) override; - void visit (AST::SlicePattern &pattern) override; - - // rust-stmt.h - void visit (AST::EmptyStmt &stmt) override; - void visit (AST::LetStmt &stmt) override; - void visit (AST::ExprStmtWithoutBlock &stmt) override; - void visit (AST::ExprStmtWithBlock &stmt) override; - - // rust-type.h - void visit (AST::TraitBound &bound) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::TraitObjectType &type) override; - void visit (AST::ParenthesisedType &type) override; - void visit (AST::ImplTraitTypeOneBound &type) override; - void visit (AST::TraitObjectTypeOneBound &type) override; - void visit (AST::TupleType &type) override; - void visit (AST::NeverType &type) override; - void visit (AST::RawPointerType &type) override; - void visit (AST::ReferenceType &type) override; - void visit (AST::ArrayType &type) override; - void visit (AST::SliceType &type) override; - void visit (AST::InferredType &type) override; - void visit (AST::BareFunctionType &type) override; - -private: - NameResolution (AST::Crate &crate, TopLevelScan &toplevel); - bool go () override; - void process_names (); - void process_work_list (); - void expand_macros (); - bool is_work_list_changed () { return is_work_list_changed_; } - std::list 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 ( \ - new AST::TypePathSegment (::std::move (seg), false, \ - Linemap::unknown_location ())); \ - ::std::vector< ::std::unique_ptr > segs; \ - segs.push_back (::std::move (typePath)); \ - auto bType = new AST::TypePath (::std::move (segs), \ - Linemap::unknown_location (), false); \ - _S.Insert (_X, bType); \ - } \ - while (0) - -namespace Rust { -namespace Analysis { - -TypeResolution::TypeResolution (AST::Crate &crate, TopLevelScan &toplevel) - : crate (crate), toplevel (toplevel) -{ - typeScope.Push (); - scope.Push (); - - // push all builtin types - this is probably too basic for future needs - ADD_BUILTIN_TYPE ("u8", typeScope); - ADD_BUILTIN_TYPE ("u16", typeScope); - ADD_BUILTIN_TYPE ("u32", typeScope); - ADD_BUILTIN_TYPE ("u64", typeScope); - - ADD_BUILTIN_TYPE ("i8", typeScope); - ADD_BUILTIN_TYPE ("i16", typeScope); - ADD_BUILTIN_TYPE ("i32", typeScope); - ADD_BUILTIN_TYPE ("i64", typeScope); - - ADD_BUILTIN_TYPE ("f32", typeScope); - ADD_BUILTIN_TYPE ("f64", typeScope); - - ADD_BUILTIN_TYPE ("char", typeScope); - ADD_BUILTIN_TYPE ("str", typeScope); - ADD_BUILTIN_TYPE ("bool", typeScope); -} - -TypeResolution::~TypeResolution () -{ - typeScope.Pop (); - scope.Pop (); -} - -bool -TypeResolution::ResolveNamesAndTypes (AST::Crate &crate, TopLevelScan &toplevel) -{ - TypeResolution resolver (crate, toplevel); - return resolver.go (); -} - -bool -TypeResolution::go () -{ - for (auto &item : crate.items) - item->accept_vis (*this); - - return true; -} - -bool -TypeResolution::typesAreCompatible (AST::Type *lhs, AST::Type *rhs, - Location locus) -{ - lhs->accept_vis (*this); - rhs->accept_vis (*this); - - auto rhsTypeStr = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - auto lhsTypeStr = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - // FIXME this needs to handle the cases of an i8 going into an i32 which is - // compatible - if (lhsTypeStr.compare (rhsTypeStr)) - { - rust_error_at (locus, "E0308: expected: %s, found %s", - lhsTypeStr.c_str (), rhsTypeStr.c_str ()); - return false; - } - - return true; -} - -void -TypeResolution::visit (AST::Token &tok) -{} - -void -TypeResolution::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -TypeResolution::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -TypeResolution::visit (AST::IdentifierExpr &ident_expr) -{ - AST::Type *type = NULL; - bool ok = scope.Lookup (ident_expr.ident, &type); - if (!ok) - { - rust_error_at (ident_expr.locus, "unknown identifier"); - return; - } - - typeBuffer.push_back (type); -} - -void -TypeResolution::visit (AST::Lifetime &lifetime) -{} - -void -TypeResolution::visit (AST::LifetimeParam &lifetime_param) -{} - -void -TypeResolution::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -TypeResolution::visit (AST::PathInExpression &path) -{ - printf ("PathInExpression: %s\n", path.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::TypePathSegment &segment) -{} -void -TypeResolution::visit (AST::TypePathSegmentGeneric &segment) -{} - -void -TypeResolution::visit (AST::TypePathSegmentFunction &segment) -{} - -void -TypeResolution::visit (AST::TypePath &path) -{ - // this may not be robust enough for type comparisons but lets try it for now - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -TypeResolution::visit (AST::QualifiedPathInExpression &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -TypeResolution::visit (AST::QualifiedPathInType &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -// rust-expr.h -void -TypeResolution::visit (AST::LiteralExpr &expr) -{ - std::string type; - switch (expr.literal.get_lit_type ()) - { - case AST::Literal::CHAR: - type = "char"; - break; - - case AST::Literal::STRING: - case AST::Literal::RAW_STRING: - type = "str"; - break; - - case AST::Literal::BOOL: - type = "bool"; - break; - - case AST::Literal::BYTE: - type = "u8"; - break; - - // FIXME these are not always going to be the case - // eg: suffix on the value can change the type - case AST::Literal::FLOAT: - type = "f32"; - break; - - case AST::Literal::INT: - type = "i32"; - break; - - case AST::Literal::BYTE_STRING: - case AST::Literal::RAW_BYTE_STRING: - // FIXME - break; - } - - if (type.empty ()) - { - rust_error_at (expr.locus, "unknown literal: %s", - expr.literal.as_string ().c_str ()); - return; - } - - AST::Type *val = NULL; - bool ok = typeScope.Lookup (type, &val); - if (ok) - typeBuffer.push_back (val); - else - rust_error_at (expr.locus, "unknown literal type: %s", type.c_str ()); -} - -void -TypeResolution::visit (AST::AttrInputLiteral &attr_input) -{} - -void -TypeResolution::visit (AST::MetaItemLitExpr &meta_item) -{} - -void -TypeResolution::visit (AST::MetaItemPathLit &meta_item) -{} - -void -TypeResolution::visit (AST::BorrowExpr &expr) -{} -void -TypeResolution::visit (AST::DereferenceExpr &expr) -{} -void -TypeResolution::visit (AST::ErrorPropagationExpr &expr) -{} -void -TypeResolution::visit (AST::NegationExpr &expr) -{} - -void -TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - size_t before; - before = typeBuffer.size (); - expr.visit_lhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.locus, "unable to determine lhs type"); - return; - } - - auto lhsType = typeBuffer.back (); - typeBuffer.pop_back (); - - before = typeBuffer.size (); - expr.visit_rhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.locus, "unable to determine rhs type"); - return; - } - - auto rhsType = typeBuffer.back (); - // not poping because we will be checking they match and the - // scope will require knowledge of the type - - // do the lhsType and the rhsType match - typesAreCompatible (lhsType, rhsType, expr.right_expr->get_locus_slow ()); -} - -void -TypeResolution::visit (AST::ComparisonExpr &expr) -{} - -void -TypeResolution::visit (AST::LazyBooleanExpr &expr) -{} - -void -TypeResolution::visit (AST::TypeCastExpr &expr) -{} - -void -TypeResolution::visit (AST::AssignmentExpr &expr) -{ - size_t before; - before = typeBuffer.size (); - expr.visit_lhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.locus, "unable to determine lhs type"); - return; - } - - auto lhsType = typeBuffer.back (); - typeBuffer.pop_back (); - - before = typeBuffer.size (); - expr.visit_rhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.locus, "unable to determine rhs type"); - return; - } - - auto rhsType = typeBuffer.back (); - // not poping because we will be checking they match and the - // scope will require knowledge of the type - - // do the lhsType and the rhsType match - if (!typesAreCompatible (lhsType, rhsType, - expr.right_expr->get_locus_slow ())) - return; - - // is the lhs mutable? -} - -void -TypeResolution::visit (AST::CompoundAssignmentExpr &expr) -{} - -void -TypeResolution::visit (AST::GroupedExpr &expr) -{} -// void TypeResolution::visit(ArrayElems& elems) {} -void -TypeResolution::visit (AST::ArrayElemsValues &elems) -{} -void -TypeResolution::visit (AST::ArrayElemsCopied &elems) -{} -void -TypeResolution::visit (AST::ArrayExpr &expr) -{} -void -TypeResolution::visit (AST::ArrayIndexExpr &expr) -{} -void -TypeResolution::visit (AST::TupleExpr &expr) -{} -void -TypeResolution::visit (AST::TupleIndexExpr &expr) -{} -void -TypeResolution::visit (AST::StructExprStruct &expr) -{} -// void TypeResolution::visit(StructExprField& field) {} -void -TypeResolution::visit (AST::StructExprFieldIdentifier &field) -{} -void -TypeResolution::visit (AST::StructExprFieldIdentifierValue &field) -{} -void -TypeResolution::visit (AST::StructExprFieldIndexValue &field) -{} -void -TypeResolution::visit (AST::StructExprStructFields &expr) -{} -void -TypeResolution::visit (AST::StructExprStructBase &expr) -{} -void -TypeResolution::visit (AST::StructExprTuple &expr) -{} -void -TypeResolution::visit (AST::StructExprUnit &expr) -{} -// void TypeResolution::visit(EnumExprField& field) {} -void -TypeResolution::visit (AST::EnumExprFieldIdentifier &field) -{} -void -TypeResolution::visit (AST::EnumExprFieldIdentifierValue &field) -{} -void -TypeResolution::visit (AST::EnumExprFieldIndexValue &field) -{} -void -TypeResolution::visit (AST::EnumExprStruct &expr) -{} -void -TypeResolution::visit (AST::EnumExprTuple &expr) -{} -void -TypeResolution::visit (AST::EnumExprFieldless &expr) -{} - -void -TypeResolution::visit (AST::CallExpr &expr) -{ - printf ("CallExpr: %s\n", expr.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::MethodCallExpr &expr) -{} -void -TypeResolution::visit (AST::FieldAccessExpr &expr) -{} -void -TypeResolution::visit (AST::ClosureExprInner &expr) -{} -void -TypeResolution::visit (AST::BlockExpr &expr) -{} -void -TypeResolution::visit (AST::ClosureExprInnerTyped &expr) -{} -void -TypeResolution::visit (AST::ContinueExpr &expr) -{} -void -TypeResolution::visit (AST::BreakExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromToExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromExpr &expr) -{} -void -TypeResolution::visit (AST::RangeToExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFullExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromToInclExpr &expr) -{} -void -TypeResolution::visit (AST::RangeToInclExpr &expr) -{} -void -TypeResolution::visit (AST::ReturnExpr &expr) -{} -void -TypeResolution::visit (AST::UnsafeBlockExpr &expr) -{} -void -TypeResolution::visit (AST::LoopExpr &expr) -{} -void -TypeResolution::visit (AST::WhileLoopExpr &expr) -{} -void -TypeResolution::visit (AST::WhileLetLoopExpr &expr) -{} -void -TypeResolution::visit (AST::ForLoopExpr &expr) -{} -void -TypeResolution::visit (AST::IfExpr &expr) -{} -void -TypeResolution::visit (AST::IfExprConseqElse &expr) -{} -void -TypeResolution::visit (AST::IfExprConseqIf &expr) -{} -void -TypeResolution::visit (AST::IfExprConseqIfLet &expr) -{} -void -TypeResolution::visit (AST::IfLetExpr &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqElse &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqIf &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqIfLet &expr) -{} -// void TypeResolution::visit(MatchCase& match_case) {} -void -TypeResolution::visit (AST::MatchCaseBlockExpr &match_case) -{} -void -TypeResolution::visit (AST::MatchCaseExpr &match_case) -{} -void -TypeResolution::visit (AST::MatchExpr &expr) -{} -void -TypeResolution::visit (AST::AwaitExpr &expr) -{} -void -TypeResolution::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -TypeResolution::visit (AST::TypeParam ¶m) -{} -// void TypeResolution::visit(WhereClauseItem& item) {} -void -TypeResolution::visit (AST::LifetimeWhereClauseItem &item) -{} -void -TypeResolution::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -TypeResolution::visit (AST::Method &method) -{} -void -TypeResolution::visit (AST::ModuleBodied &module) -{} -void -TypeResolution::visit (AST::ModuleNoBody &module) -{} -void -TypeResolution::visit (AST::ExternCrate &crate) -{} -// void TypeResolution::visit(UseTree& use_tree) {} -void -TypeResolution::visit (AST::UseTreeGlob &use_tree) -{} -void -TypeResolution::visit (AST::UseTreeList &use_tree) -{} -void -TypeResolution::visit (AST::UseTreeRebind &use_tree) -{} -void -TypeResolution::visit (AST::UseDeclaration &use_decl) -{} - -void -TypeResolution::visit (AST::Function &function) -{ - // always emit the function with return type in the event of nil return type - // its a marker for a void function - scope.Insert (function.function_name, function.return_type.get ()); - - scope.Push (); - for (auto ¶m : function.function_params) - { - auto before = letPatternBuffer.size (); - param.param_name->accept_vis (*this); - if (letPatternBuffer.size () <= before) - { - rust_error_at (param.locus, "failed to analyse parameter name"); - return; - } - - auto paramName = letPatternBuffer.back (); - letPatternBuffer.pop_back (); - scope.Insert (paramName.variable_ident, param.type.get ()); - } - - // walk the expression body - for (auto &stmt : function.function_body->statements) - { - stmt->accept_vis (*this); - } - - scope.Pop (); -} - -void -TypeResolution::visit (AST::TypeAlias &type_alias) -{} -void -TypeResolution::visit (AST::StructStruct &struct_item) -{} -void -TypeResolution::visit (AST::TupleStruct &tuple_struct) -{} -void -TypeResolution::visit (AST::EnumItem &item) -{} -void -TypeResolution::visit (AST::EnumItemTuple &item) -{} -void -TypeResolution::visit (AST::EnumItemStruct &item) -{} -void -TypeResolution::visit (AST::EnumItemDiscriminant &item) -{} -void -TypeResolution::visit (AST::Enum &enum_item) -{} -void -TypeResolution::visit (AST::Union &union_item) -{} - -void -TypeResolution::visit (AST::ConstantItem &const_item) -{ - printf ("ConstantItem: %s\n", const_item.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::StaticItem &static_item) -{} -void -TypeResolution::visit (AST::TraitItemFunc &item) -{} -void -TypeResolution::visit (AST::TraitItemMethod &item) -{} -void -TypeResolution::visit (AST::TraitItemConst &item) -{} -void -TypeResolution::visit (AST::TraitItemType &item) -{} -void -TypeResolution::visit (AST::Trait &trait) -{} -void -TypeResolution::visit (AST::InherentImpl &impl) -{} -void -TypeResolution::visit (AST::TraitImpl &impl) -{} -// void TypeResolution::visit(ExternalItem& item) {} -void -TypeResolution::visit (AST::ExternalStaticItem &item) -{} -void -TypeResolution::visit (AST::ExternalFunctionItem &item) -{} -void -TypeResolution::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -TypeResolution::visit (AST::MacroMatchFragment &match) -{} -void -TypeResolution::visit (AST::MacroMatchRepetition &match) -{} -void -TypeResolution::visit (AST::MacroMatcher &matcher) -{} -void -TypeResolution::visit (AST::MacroRulesDefinition &rules_def) -{} -void -TypeResolution::visit (AST::MacroInvocation ¯o_invoc) -{} -void -TypeResolution::visit (AST::MetaItemPath &meta_item) -{} -void -TypeResolution::visit (AST::MetaItemSeq &meta_item) -{} -void -TypeResolution::visit (AST::MetaWord &meta_item) -{} -void -TypeResolution::visit (AST::MetaNameValueStr &meta_item) -{} -void -TypeResolution::visit (AST::MetaListPaths &meta_item) -{} -void -TypeResolution::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -TypeResolution::visit (AST::LiteralPattern &pattern) -{ - printf ("LiteralPattern: %s\n", pattern.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::IdentifierPattern &pattern) -{ - letPatternBuffer.push_back (pattern); -} - -void -TypeResolution::visit (AST::WildcardPattern &pattern) -{} -// void TypeResolution::visit(RangePatternBound& bound) {} -void -TypeResolution::visit (AST::RangePatternBoundLiteral &bound) -{} -void -TypeResolution::visit (AST::RangePatternBoundPath &bound) -{} -void -TypeResolution::visit (AST::RangePatternBoundQualPath &bound) -{} -void -TypeResolution::visit (AST::RangePattern &pattern) -{} -void -TypeResolution::visit (AST::ReferencePattern &pattern) -{} -// void TypeResolution::visit(StructPatternField& field) {} -void -TypeResolution::visit (AST::StructPatternFieldTuplePat &field) -{} -void -TypeResolution::visit (AST::StructPatternFieldIdentPat &field) -{} -void -TypeResolution::visit (AST::StructPatternFieldIdent &field) -{} -void -TypeResolution::visit (AST::StructPattern &pattern) -{} -// void TypeResolution::visit(TupleStructItems& tuple_items) {} -void -TypeResolution::visit (AST::TupleStructItemsNoRange &tuple_items) -{} -void -TypeResolution::visit (AST::TupleStructItemsRange &tuple_items) -{} -void -TypeResolution::visit (AST::TupleStructPattern &pattern) -{} -// void TypeResolution::visit(TuplePatternItems& tuple_items) {} -void -TypeResolution::visit (AST::TuplePatternItemsMultiple &tuple_items) -{} -void -TypeResolution::visit (AST::TuplePatternItemsRanged &tuple_items) -{} -void -TypeResolution::visit (AST::TuplePattern &pattern) -{} -void -TypeResolution::visit (AST::GroupedPattern &pattern) -{} -void -TypeResolution::visit (AST::SlicePattern &pattern) -{} - -// rust-stmt.h -void -TypeResolution::visit (AST::EmptyStmt &stmt) -{} - -void -TypeResolution::visit (AST::LetStmt &stmt) -{ - if (!stmt.has_init_expr () && !stmt.has_type ()) - { - rust_error_at (stmt.locus, - "E0282: type annotations or init expression needed"); - return; - } - - AST::Type *inferedType = NULL; - if (stmt.has_init_expr ()) - { - stmt.init_expr->accept_vis (*this); - - if (typeBuffer.empty ()) - { - rust_error_at ( - stmt.init_expr->get_locus_slow (), - "unable to determine type for declaration from init expr"); - return; - } - - inferedType = typeBuffer.back (); - typeBuffer.pop_back (); - } - - if (stmt.has_type () && stmt.has_init_expr ()) - { - if (!typesAreCompatible (stmt.type.get (), inferedType, - stmt.init_expr->get_locus_slow ())) - { - return; - } - } - else if (stmt.has_type () && !stmt.has_init_expr ()) - { - inferedType = stmt.type.get (); - } - - // TODO check we know what the type is in the scope requires the builtins to - // be defined at the constructor - - // ensure the decl has the type set for compilation later on - if (!stmt.has_type ()) - { - // FIXME - // stmt.type = inferedType; - } - - // get all the names part of this declaration and add the types to the scope - stmt.variables_pattern->accept_vis (*this); - for (auto it = letPatternBuffer.begin (); it != letPatternBuffer.end (); it++) - { - scope.Insert (it->variable_ident, inferedType); - } - letPatternBuffer.clear (); -} - -void -TypeResolution::visit (AST::ExprStmtWithoutBlock &stmt) -{ - stmt.expr->accept_vis (*this); -} - -void -TypeResolution::visit (AST::ExprStmtWithBlock &stmt) -{} - -// rust-type.h -void -TypeResolution::visit (AST::TraitBound &bound) -{} - -void -TypeResolution::visit (AST::ImplTraitType &type) -{} - -void -TypeResolution::visit (AST::TraitObjectType &type) -{} -void -TypeResolution::visit (AST::ParenthesisedType &type) -{} -void -TypeResolution::visit (AST::ImplTraitTypeOneBound &type) -{} -void -TypeResolution::visit (AST::TraitObjectTypeOneBound &type) -{} -void -TypeResolution::visit (AST::TupleType &type) -{} -void -TypeResolution::visit (AST::NeverType &type) -{} -void -TypeResolution::visit (AST::RawPointerType &type) -{} -void -TypeResolution::visit (AST::ReferenceType &type) -{} -void -TypeResolution::visit (AST::ArrayType &type) -{} -void -TypeResolution::visit (AST::SliceType &type) -{} -void -TypeResolution::visit (AST::InferredType &type) -{} -void -TypeResolution::visit (AST::BareFunctionType &type) -{} - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-resolution.h b/gcc/rust/analysis/rust-resolution.h deleted file mode 100644 index 9eb4b95..0000000 --- a/gcc/rust/analysis/rust-resolution.h +++ /dev/null @@ -1,51 +0,0 @@ -#pragma once - -#include "rust-system.h" -#include "rust-ast-full.h" -#include "rust-ast-visitor.h" -#include "rust-scan.h" -#include "scope.h" - -namespace Rust { -namespace Analysis { - -class Resolution : public AST::ASTVisitor -{ -public: - virtual ~Resolution () - { - scope.Pop (); - valueScope.Pop (); - macroScope.Pop (); - typeScope.Pop (); - }; - -private: - virtual bool go () = 0; - -protected: - Resolution (AST::Crate &crate, TopLevelScan &toplevel) - : crate (crate), toplevel (toplevel) - { - scope.Push (); - valueScope.Push (); - macroScope.Push (); - typeScope.Push (); - }; - - Scope scope; - Scope valueScope; - Scope macroScope; - Scope typeScope; - - AST::Crate &crate; - TopLevelScan &toplevel; - - std::vector letPatternBuffer; - std::vector typeBuffer; - std::vector typeComparisonBuffer; - std::vector functionLookup; -}; - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-scan.cc b/gcc/rust/analysis/rust-scan.cc deleted file mode 100644 index 31c89e4..0000000 --- a/gcc/rust/analysis/rust-scan.cc +++ /dev/null @@ -1,593 +0,0 @@ -#include "rust-scan.h" -#include "rust-diagnostics.h" - -namespace Rust { -namespace Analysis { - -TopLevelScan::TopLevelScan (AST::Crate &crate) : crate (crate) -{ - for (auto &item : crate.items) - item->accept_vis (*this); -} - -TopLevelScan::~TopLevelScan () {} - -AST::Function * -TopLevelScan::lookupFunction (AST::Expr *expr) -{ - auto before = fnLookup.size (); - expr->accept_vis (*this); - if (fnLookup.size () > before) - { - AST::Function *fndecl = fnLookup.back (); - fnLookup.pop_back (); - return fndecl; - } - return NULL; -} - -void -TopLevelScan::visit (AST::Token &tok) -{} - -void -TopLevelScan::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -TopLevelScan::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -TopLevelScan::visit (AST::IdentifierExpr &ident_expr) -{} - -void -TopLevelScan::visit (AST::Lifetime &lifetime) -{} - -void -TopLevelScan::visit (AST::LifetimeParam &lifetime_param) -{} - -void -TopLevelScan::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -TopLevelScan::visit (AST::PathInExpression &path) -{ - auto it = functions.find (path.as_string ()); - bool foundFndecl = it != functions.end (); - if (foundFndecl) - { - fnLookup.push_back (it->second); - return; - } -} - -void -TopLevelScan::visit (AST::TypePathSegment &segment) -{} -void -TopLevelScan::visit (AST::TypePathSegmentGeneric &segment) -{} - -void -TopLevelScan::visit (AST::TypePathSegmentFunction &segment) -{} - -void -TopLevelScan::visit (AST::TypePath &path) -{} - -void -TopLevelScan::visit (AST::QualifiedPathInExpression &path) -{} - -void -TopLevelScan::visit (AST::QualifiedPathInType &path) -{} - -// rust-expr.h -void -TopLevelScan::visit (AST::LiteralExpr &expr) -{} - -void -TopLevelScan::visit (AST::AttrInputLiteral &attr_input) -{} - -void -TopLevelScan::visit (AST::MetaItemLitExpr &meta_item) -{} - -void -TopLevelScan::visit (AST::MetaItemPathLit &meta_item) -{} - -void -TopLevelScan::visit (AST::BorrowExpr &expr) -{} -void -TopLevelScan::visit (AST::DereferenceExpr &expr) -{} -void -TopLevelScan::visit (AST::ErrorPropagationExpr &expr) -{} -void -TopLevelScan::visit (AST::NegationExpr &expr) -{} - -void -TopLevelScan::visit (AST::ArithmeticOrLogicalExpr &expr) -{} - -void -TopLevelScan::visit (AST::ComparisonExpr &expr) -{} - -void -TopLevelScan::visit (AST::LazyBooleanExpr &expr) -{} - -void -TopLevelScan::visit (AST::TypeCastExpr &expr) -{} - -void -TopLevelScan::visit (AST::AssignmentExpr &expr) -{} - -void -TopLevelScan::visit (AST::CompoundAssignmentExpr &expr) -{} - -void -TopLevelScan::visit (AST::GroupedExpr &expr) -{} -// void TopLevelScan::visit(ArrayElems& elems) {} -void -TopLevelScan::visit (AST::ArrayElemsValues &elems) -{} -void -TopLevelScan::visit (AST::ArrayElemsCopied &elems) -{} -void -TopLevelScan::visit (AST::ArrayExpr &expr) -{} -void -TopLevelScan::visit (AST::ArrayIndexExpr &expr) -{} -void -TopLevelScan::visit (AST::TupleExpr &expr) -{} -void -TopLevelScan::visit (AST::TupleIndexExpr &expr) -{} -void -TopLevelScan::visit (AST::StructExprStruct &expr) -{} -// void TopLevelScan::visit(StructExprField& field) {} -void -TopLevelScan::visit (AST::StructExprFieldIdentifier &field) -{} -void -TopLevelScan::visit (AST::StructExprFieldIdentifierValue &field) -{} -void -TopLevelScan::visit (AST::StructExprFieldIndexValue &field) -{} -void -TopLevelScan::visit (AST::StructExprStructFields &expr) -{} -void -TopLevelScan::visit (AST::StructExprStructBase &expr) -{} -void -TopLevelScan::visit (AST::StructExprTuple &expr) -{} -void -TopLevelScan::visit (AST::StructExprUnit &expr) -{} -// void TopLevelScan::visit(EnumExprField& field) {} -void -TopLevelScan::visit (AST::EnumExprFieldIdentifier &field) -{} -void -TopLevelScan::visit (AST::EnumExprFieldIdentifierValue &field) -{} -void -TopLevelScan::visit (AST::EnumExprFieldIndexValue &field) -{} -void -TopLevelScan::visit (AST::EnumExprStruct &expr) -{} -void -TopLevelScan::visit (AST::EnumExprTuple &expr) -{} -void -TopLevelScan::visit (AST::EnumExprFieldless &expr) -{} - -void -TopLevelScan::visit (AST::CallExpr &expr) -{} - -void -TopLevelScan::visit (AST::MethodCallExpr &expr) -{} -void -TopLevelScan::visit (AST::FieldAccessExpr &expr) -{} -void -TopLevelScan::visit (AST::ClosureExprInner &expr) -{} -void -TopLevelScan::visit (AST::BlockExpr &expr) -{} -void -TopLevelScan::visit (AST::ClosureExprInnerTyped &expr) -{} -void -TopLevelScan::visit (AST::ContinueExpr &expr) -{} -void -TopLevelScan::visit (AST::BreakExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeFromToExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeFromExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeToExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeFullExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeFromToInclExpr &expr) -{} -void -TopLevelScan::visit (AST::RangeToInclExpr &expr) -{} -void -TopLevelScan::visit (AST::ReturnExpr &expr) -{} -void -TopLevelScan::visit (AST::UnsafeBlockExpr &expr) -{} -void -TopLevelScan::visit (AST::LoopExpr &expr) -{} -void -TopLevelScan::visit (AST::WhileLoopExpr &expr) -{} -void -TopLevelScan::visit (AST::WhileLetLoopExpr &expr) -{} -void -TopLevelScan::visit (AST::ForLoopExpr &expr) -{} -void -TopLevelScan::visit (AST::IfExpr &expr) -{} -void -TopLevelScan::visit (AST::IfExprConseqElse &expr) -{} -void -TopLevelScan::visit (AST::IfExprConseqIf &expr) -{} -void -TopLevelScan::visit (AST::IfExprConseqIfLet &expr) -{} -void -TopLevelScan::visit (AST::IfLetExpr &expr) -{} -void -TopLevelScan::visit (AST::IfLetExprConseqElse &expr) -{} -void -TopLevelScan::visit (AST::IfLetExprConseqIf &expr) -{} -void -TopLevelScan::visit (AST::IfLetExprConseqIfLet &expr) -{} -// void TopLevelScan::visit(MatchCase& match_case) {} -/*void -TopLevelScan::visit (AST::MatchCaseBlockExpr &match_case) -{}*/ -/*void -TopLevelScan::visit (AST::MatchCaseExpr &match_case) -{}*/ -void -TopLevelScan::visit (AST::MatchExpr &expr) -{} -void -TopLevelScan::visit (AST::AwaitExpr &expr) -{} -void -TopLevelScan::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -TopLevelScan::visit (AST::TypeParam ¶m) -{} -// void TopLevelScan::visit(WhereClauseItem& item) {} -void -TopLevelScan::visit (AST::LifetimeWhereClauseItem &item) -{} -void -TopLevelScan::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -TopLevelScan::visit (AST::Method &method) -{} -void -TopLevelScan::visit (AST::ModuleBodied &module) -{} -void -TopLevelScan::visit (AST::ModuleNoBody &module) -{} -void -TopLevelScan::visit (AST::ExternCrate &crate) -{} -// void TopLevelScan::visit(UseTree& use_tree) {} -void -TopLevelScan::visit (AST::UseTreeGlob &use_tree) -{} -void -TopLevelScan::visit (AST::UseTreeList &use_tree) -{} -void -TopLevelScan::visit (AST::UseTreeRebind &use_tree) -{} -void -TopLevelScan::visit (AST::UseDeclaration &use_decl) -{} - -void -TopLevelScan::visit (AST::Function &function) -{ - functions[function.get_function_name ()] = &function; -} - -void -TopLevelScan::visit (AST::TypeAlias &type_alias) -{} -void -TopLevelScan::visit (AST::StructStruct &struct_item) -{} -void -TopLevelScan::visit (AST::TupleStruct &tuple_struct) -{} -void -TopLevelScan::visit (AST::EnumItem &item) -{} -void -TopLevelScan::visit (AST::EnumItemTuple &item) -{} -void -TopLevelScan::visit (AST::EnumItemStruct &item) -{} -void -TopLevelScan::visit (AST::EnumItemDiscriminant &item) -{} -void -TopLevelScan::visit (AST::Enum &enum_item) -{} -void -TopLevelScan::visit (AST::Union &union_item) -{} - -void -TopLevelScan::visit (AST::ConstantItem &const_item) -{} - -void -TopLevelScan::visit (AST::StaticItem &static_item) -{} -void -TopLevelScan::visit (AST::TraitItemFunc &item) -{} -void -TopLevelScan::visit (AST::TraitItemMethod &item) -{} -void -TopLevelScan::visit (AST::TraitItemConst &item) -{} -void -TopLevelScan::visit (AST::TraitItemType &item) -{} -void -TopLevelScan::visit (AST::Trait &trait) -{} -void -TopLevelScan::visit (AST::InherentImpl &impl) -{} -void -TopLevelScan::visit (AST::TraitImpl &impl) -{} -// void TopLevelScan::visit(ExternalItem& item) {} -void -TopLevelScan::visit (AST::ExternalStaticItem &item) -{} -void -TopLevelScan::visit (AST::ExternalFunctionItem &item) -{} -void -TopLevelScan::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -TopLevelScan::visit (AST::MacroMatchFragment &match) -{} -void -TopLevelScan::visit (AST::MacroMatchRepetition &match) -{} -void -TopLevelScan::visit (AST::MacroMatcher &matcher) -{} -void -TopLevelScan::visit (AST::MacroRulesDefinition &rules_def) -{} -void -TopLevelScan::visit (AST::MacroInvocation ¯o_invoc) -{} -void -TopLevelScan::visit (AST::MetaItemPath &meta_item) -{} -void -TopLevelScan::visit (AST::MetaItemSeq &meta_item) -{} -void -TopLevelScan::visit (AST::MetaWord &meta_item) -{} -void -TopLevelScan::visit (AST::MetaNameValueStr &meta_item) -{} -void -TopLevelScan::visit (AST::MetaListPaths &meta_item) -{} -void -TopLevelScan::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -TopLevelScan::visit (AST::LiteralPattern &pattern) -{} - -void -TopLevelScan::visit (AST::IdentifierPattern &pattern) -{} - -void -TopLevelScan::visit (AST::WildcardPattern &pattern) -{} -// void TopLevelScan::visit(RangePatternBound& bound) {} -void -TopLevelScan::visit (AST::RangePatternBoundLiteral &bound) -{} -void -TopLevelScan::visit (AST::RangePatternBoundPath &bound) -{} -void -TopLevelScan::visit (AST::RangePatternBoundQualPath &bound) -{} -void -TopLevelScan::visit (AST::RangePattern &pattern) -{} -void -TopLevelScan::visit (AST::ReferencePattern &pattern) -{} -// void TopLevelScan::visit(StructPatternField& field) {} -void -TopLevelScan::visit (AST::StructPatternFieldTuplePat &field) -{} -void -TopLevelScan::visit (AST::StructPatternFieldIdentPat &field) -{} -void -TopLevelScan::visit (AST::StructPatternFieldIdent &field) -{} -void -TopLevelScan::visit (AST::StructPattern &pattern) -{} -// void TopLevelScan::visit(TupleStructItems& tuple_items) {} -void -TopLevelScan::visit (AST::TupleStructItemsNoRange &tuple_items) -{} -void -TopLevelScan::visit (AST::TupleStructItemsRange &tuple_items) -{} -void -TopLevelScan::visit (AST::TupleStructPattern &pattern) -{} -// void TopLevelScan::visit(TuplePatternItems& tuple_items) {} -void -TopLevelScan::visit (AST::TuplePatternItemsMultiple &tuple_items) -{} -void -TopLevelScan::visit (AST::TuplePatternItemsRanged &tuple_items) -{} -void -TopLevelScan::visit (AST::TuplePattern &pattern) -{} -void -TopLevelScan::visit (AST::GroupedPattern &pattern) -{} -void -TopLevelScan::visit (AST::SlicePattern &pattern) -{} - -// rust-stmt.h -void -TopLevelScan::visit (AST::EmptyStmt &stmt) -{} - -void -TopLevelScan::visit (AST::LetStmt &stmt) -{} - -void -TopLevelScan::visit (AST::ExprStmtWithoutBlock &stmt) -{} - -void -TopLevelScan::visit (AST::ExprStmtWithBlock &stmt) -{} - -// rust-type.h -void -TopLevelScan::visit (AST::TraitBound &bound) -{} - -void -TopLevelScan::visit (AST::ImplTraitType &type) -{} - -void -TopLevelScan::visit (AST::TraitObjectType &type) -{} -void -TopLevelScan::visit (AST::ParenthesisedType &type) -{} -void -TopLevelScan::visit (AST::ImplTraitTypeOneBound &type) -{} -void -TopLevelScan::visit (AST::TraitObjectTypeOneBound &type) -{} -void -TopLevelScan::visit (AST::TupleType &type) -{} -void -TopLevelScan::visit (AST::NeverType &type) -{} -void -TopLevelScan::visit (AST::RawPointerType &type) -{} -void -TopLevelScan::visit (AST::ReferenceType &type) -{} -void -TopLevelScan::visit (AST::ArrayType &type) -{} -void -TopLevelScan::visit (AST::SliceType &type) -{} -void -TopLevelScan::visit (AST::InferredType &type) -{} -void -TopLevelScan::visit (AST::BareFunctionType &type) -{} - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-scan.h b/gcc/rust/analysis/rust-scan.h deleted file mode 100644 index 77beeca..0000000 --- a/gcc/rust/analysis/rust-scan.h +++ /dev/null @@ -1,233 +0,0 @@ -#pragma once - -#include "rust-system.h" -#include "rust-ast-full.h" -#include "rust-ast-visitor.h" -#include "scope.h" - -namespace Rust { -namespace Analysis { - -class TopLevelScan : public AST::ASTVisitor -{ -public: - TopLevelScan (AST::Crate &crate); - - ~TopLevelScan (); - - AST::Function *lookupFunction (AST::Expr *expr); - - // visitor impl - // rust-ast.h - // virtual void visit(AttrInput& attr_input); - // virtual void visit(TokenTree& token_tree); - // virtual void visit(MacroMatch& macro_match); - virtual void visit (AST::Token &tok); - virtual void visit (AST::DelimTokenTree &delim_tok_tree); - virtual void visit (AST::AttrInputMetaItemContainer &input); - // virtual void visit(MetaItem& meta_item); - // virtual void vsit(Stmt& stmt); - // virtual void visit(Expr& expr); - virtual void visit (AST::IdentifierExpr &ident_expr); - // virtual void visit(Pattern& pattern); - // virtual void visit(Type& type); - // virtual void visit(TypeParamBound& type_param_bound); - virtual void visit (AST::Lifetime &lifetime); - // virtual void visit(GenericParam& generic_param); - virtual void visit (AST::LifetimeParam &lifetime_param); - // virtual void visit(TraitItem& trait_item); - // virtual void visit(InherentImplItem& inherent_impl_item); - // virtual void visit(TraitImplItem& trait_impl_item); - virtual void visit (AST::MacroInvocationSemi ¯o); - - // rust-path.h - virtual void visit (AST::PathInExpression &path); - virtual void visit (AST::TypePathSegment &segment); - virtual void visit (AST::TypePathSegmentGeneric &segment); - virtual void visit (AST::TypePathSegmentFunction &segment); - virtual void visit (AST::TypePath &path); - virtual void visit (AST::QualifiedPathInExpression &path); - virtual void visit (AST::QualifiedPathInType &path); - - // rust-expr.h - virtual void visit (AST::LiteralExpr &expr); - virtual void visit (AST::AttrInputLiteral &attr_input); - virtual void visit (AST::MetaItemLitExpr &meta_item); - virtual void visit (AST::MetaItemPathLit &meta_item); - virtual void visit (AST::BorrowExpr &expr); - virtual void visit (AST::DereferenceExpr &expr); - virtual void visit (AST::ErrorPropagationExpr &expr); - virtual void visit (AST::NegationExpr &expr); - virtual void visit (AST::ArithmeticOrLogicalExpr &expr); - virtual void visit (AST::ComparisonExpr &expr); - virtual void visit (AST::LazyBooleanExpr &expr); - virtual void visit (AST::TypeCastExpr &expr); - virtual void visit (AST::AssignmentExpr &expr); - virtual void visit (AST::CompoundAssignmentExpr &expr); - virtual void visit (AST::GroupedExpr &expr); - // virtual void visit(ArrayElems& elems); - virtual void visit (AST::ArrayElemsValues &elems); - virtual void visit (AST::ArrayElemsCopied &elems); - virtual void visit (AST::ArrayExpr &expr); - virtual void visit (AST::ArrayIndexExpr &expr); - virtual void visit (AST::TupleExpr &expr); - virtual void visit (AST::TupleIndexExpr &expr); - virtual void visit (AST::StructExprStruct &expr); - // virtual void visit(StructExprField& field); - virtual void visit (AST::StructExprFieldIdentifier &field); - virtual void visit (AST::StructExprFieldIdentifierValue &field); - virtual void visit (AST::StructExprFieldIndexValue &field); - virtual void visit (AST::StructExprStructFields &expr); - virtual void visit (AST::StructExprStructBase &expr); - virtual void visit (AST::StructExprTuple &expr); - virtual void visit (AST::StructExprUnit &expr); - // virtual void visit(EnumExprField& field); - virtual void visit (AST::EnumExprFieldIdentifier &field); - virtual void visit (AST::EnumExprFieldIdentifierValue &field); - virtual void visit (AST::EnumExprFieldIndexValue &field); - virtual void visit (AST::EnumExprStruct &expr); - virtual void visit (AST::EnumExprTuple &expr); - virtual void visit (AST::EnumExprFieldless &expr); - virtual void visit (AST::CallExpr &expr); - virtual void visit (AST::MethodCallExpr &expr); - virtual void visit (AST::FieldAccessExpr &expr); - virtual void visit (AST::ClosureExprInner &expr); - virtual void visit (AST::BlockExpr &expr); - virtual void visit (AST::ClosureExprInnerTyped &expr); - virtual void visit (AST::ContinueExpr &expr); - virtual void visit (AST::BreakExpr &expr); - virtual void visit (AST::RangeFromToExpr &expr); - virtual void visit (AST::RangeFromExpr &expr); - virtual void visit (AST::RangeToExpr &expr); - virtual void visit (AST::RangeFullExpr &expr); - virtual void visit (AST::RangeFromToInclExpr &expr); - virtual void visit (AST::RangeToInclExpr &expr); - virtual void visit (AST::ReturnExpr &expr); - virtual void visit (AST::UnsafeBlockExpr &expr); - virtual void visit (AST::LoopExpr &expr); - virtual void visit (AST::WhileLoopExpr &expr); - virtual void visit (AST::WhileLetLoopExpr &expr); - virtual void visit (AST::ForLoopExpr &expr); - virtual void visit (AST::IfExpr &expr); - virtual void visit (AST::IfExprConseqElse &expr); - virtual void visit (AST::IfExprConseqIf &expr); - virtual void visit (AST::IfExprConseqIfLet &expr); - virtual void visit (AST::IfLetExpr &expr); - virtual void visit (AST::IfLetExprConseqElse &expr); - virtual void visit (AST::IfLetExprConseqIf &expr); - virtual void visit (AST::IfLetExprConseqIfLet &expr); - // virtual void visit(MatchCase& match_case); - // virtual void visit (AST::MatchCaseBlockExpr &match_case); - // virtual void visit (AST::MatchCaseExpr &match_case); - virtual void visit (AST::MatchExpr &expr); - virtual void visit (AST::AwaitExpr &expr); - virtual void visit (AST::AsyncBlockExpr &expr); - - // rust-item.h - virtual void visit (AST::TypeParam ¶m); - // virtual void visit(WhereClauseItem& item); - virtual void visit (AST::LifetimeWhereClauseItem &item); - virtual void visit (AST::TypeBoundWhereClauseItem &item); - virtual void visit (AST::Method &method); - virtual void visit (AST::ModuleBodied &module); - virtual void visit (AST::ModuleNoBody &module); - virtual void visit (AST::ExternCrate &crate); - // virtual void visit(UseTree& use_tree); - virtual void visit (AST::UseTreeGlob &use_tree); - virtual void visit (AST::UseTreeList &use_tree); - virtual void visit (AST::UseTreeRebind &use_tree); - virtual void visit (AST::UseDeclaration &use_decl); - virtual void visit (AST::Function &function); - virtual void visit (AST::TypeAlias &type_alias); - virtual void visit (AST::StructStruct &struct_item); - virtual void visit (AST::TupleStruct &tuple_struct); - virtual void visit (AST::EnumItem &item); - virtual void visit (AST::EnumItemTuple &item); - virtual void visit (AST::EnumItemStruct &item); - virtual void visit (AST::EnumItemDiscriminant &item); - virtual void visit (AST::Enum &enum_item); - virtual void visit (AST::Union &union_item); - virtual void visit (AST::ConstantItem &const_item); - virtual void visit (AST::StaticItem &static_item); - virtual void visit (AST::TraitItemFunc &item); - virtual void visit (AST::TraitItemMethod &item); - virtual void visit (AST::TraitItemConst &item); - virtual void visit (AST::TraitItemType &item); - virtual void visit (AST::Trait &trait); - virtual void visit (AST::InherentImpl &impl); - virtual void visit (AST::TraitImpl &impl); - // virtual void visit(ExternalItem& item); - virtual void visit (AST::ExternalStaticItem &item); - virtual void visit (AST::ExternalFunctionItem &item); - virtual void visit (AST::ExternBlock &block); - - // rust-macro.h - virtual void visit (AST::MacroMatchFragment &match); - virtual void visit (AST::MacroMatchRepetition &match); - virtual void visit (AST::MacroMatcher &matcher); - virtual void visit (AST::MacroRulesDefinition &rules_def); - virtual void visit (AST::MacroInvocation ¯o_invoc); - virtual void visit (AST::MetaItemPath &meta_item); - virtual void visit (AST::MetaItemSeq &meta_item); - virtual void visit (AST::MetaWord &meta_item); - virtual void visit (AST::MetaNameValueStr &meta_item); - virtual void visit (AST::MetaListPaths &meta_item); - virtual void visit (AST::MetaListNameValueStr &meta_item); - - // rust-pattern.h - virtual void visit (AST::LiteralPattern &pattern); - virtual void visit (AST::IdentifierPattern &pattern); - virtual void visit (AST::WildcardPattern &pattern); - // virtual void visit(RangePatternBound& bound); - virtual void visit (AST::RangePatternBoundLiteral &bound); - virtual void visit (AST::RangePatternBoundPath &bound); - virtual void visit (AST::RangePatternBoundQualPath &bound); - virtual void visit (AST::RangePattern &pattern); - virtual void visit (AST::ReferencePattern &pattern); - // virtual void visit(StructPatternField& field); - virtual void visit (AST::StructPatternFieldTuplePat &field); - virtual void visit (AST::StructPatternFieldIdentPat &field); - virtual void visit (AST::StructPatternFieldIdent &field); - virtual void visit (AST::StructPattern &pattern); - // virtual void visit(TupleStructItems& tuple_items); - virtual void visit (AST::TupleStructItemsNoRange &tuple_items); - virtual void visit (AST::TupleStructItemsRange &tuple_items); - virtual void visit (AST::TupleStructPattern &pattern); - // virtual void visit(TuplePatternItems& tuple_items); - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items); - virtual void visit (AST::TuplePatternItemsRanged &tuple_items); - virtual void visit (AST::TuplePattern &pattern); - virtual void visit (AST::GroupedPattern &pattern); - virtual void visit (AST::SlicePattern &pattern); - - // rust-stmt.h - virtual void visit (AST::EmptyStmt &stmt); - virtual void visit (AST::LetStmt &stmt); - virtual void visit (AST::ExprStmtWithoutBlock &stmt); - virtual void visit (AST::ExprStmtWithBlock &stmt); - - // rust-type.h - virtual void visit (AST::TraitBound &bound); - virtual void visit (AST::ImplTraitType &type); - virtual void visit (AST::TraitObjectType &type); - virtual void visit (AST::ParenthesisedType &type); - virtual void visit (AST::ImplTraitTypeOneBound &type); - virtual void visit (AST::TraitObjectTypeOneBound &type); - virtual void visit (AST::TupleType &type); - virtual void visit (AST::NeverType &type); - virtual void visit (AST::RawPointerType &type); - virtual void visit (AST::ReferenceType &type); - virtual void visit (AST::ArrayType &type); - virtual void visit (AST::SliceType &type); - virtual void visit (AST::InferredType &type); - virtual void visit (AST::BareFunctionType &type); - -private: - std::map functions; - AST::Crate &crate; - - std::vector 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 ( \ - new AST::TypePathSegment (::std::move (seg), false, \ - Linemap::predeclared_location ())); \ - ::std::vector< ::std::unique_ptr > segs; \ - segs.push_back (::std::move (typePath)); \ - auto bType \ - = new AST::TypePath (::std::move (segs), \ - Linemap::predeclared_location (), false); \ - _S.InsertType (_X, bType); \ - } \ - while (0) - -namespace Rust { -namespace Analysis { - -TypeResolution::TypeResolution (AST::Crate &crate, TopLevelScan &toplevel) - : Resolution (crate, toplevel) -{ - scope.Push (); - - // push all builtin types - this is probably too basic for future needs - ADD_BUILTIN_TYPE ("u8", scope); - ADD_BUILTIN_TYPE ("u16", scope); - ADD_BUILTIN_TYPE ("u32", scope); - ADD_BUILTIN_TYPE ("u64", scope); - - ADD_BUILTIN_TYPE ("i8", scope); - ADD_BUILTIN_TYPE ("i16", scope); - ADD_BUILTIN_TYPE ("i32", scope); - ADD_BUILTIN_TYPE ("i64", scope); - - ADD_BUILTIN_TYPE ("f32", scope); - ADD_BUILTIN_TYPE ("f64", scope); - - ADD_BUILTIN_TYPE ("char", scope); - ADD_BUILTIN_TYPE ("str", scope); - ADD_BUILTIN_TYPE ("bool", scope); - - // now its the crate scope - scope.Push (); -} - -TypeResolution::~TypeResolution () -{ - scope.Pop (); // crate - scope.Pop (); // builtins -} - -bool -TypeResolution::Resolve (AST::Crate &crate, TopLevelScan &toplevel) -{ - TypeResolution resolver (crate, toplevel); - return resolver.go (); -} - -bool -TypeResolution::go () -{ - for (auto &item : crate.items) - item->accept_vis (*this); - - return true; -} - -bool -TypeResolution::typesAreCompatible (AST::Type *lhs, AST::Type *rhs, - Location locus) -{ - auto before = typeComparisonBuffer.size (); - lhs->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (locus, "failed to understand type for lhs"); - return false; - } - - auto lhsTypeStr = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - rhs->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (locus, "failed to understand type for rhs"); - return false; - } - - auto rhsTypeStr = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - // FIXME this needs to handle the cases of an i8 going into an i32 which is - // compatible - if (lhsTypeStr.compare (rhsTypeStr)) - { - rust_error_at (locus, "E0308: expected: %s, found %s", - lhsTypeStr.c_str (), rhsTypeStr.c_str ()); - return false; - } - - AST::Type *val = NULL; - if (!scope.LookupType (lhsTypeStr, &val)) - { - rust_error_at (locus, "Unknown type: %s", lhsTypeStr.c_str ()); - return false; - } - - return true; -} - -bool -TypeResolution::isTypeInScope (AST::Type *type, Location locus) -{ - auto before = typeComparisonBuffer.size (); - type->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (locus, "unable to decipher type: %s", - type->as_string ().c_str ()); - return false; - } - - auto t = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - AST::Type *val = NULL; - return scope.LookupType (t, &val); -} - -AST::Function * -TypeResolution::lookupFndecl (AST::Expr *expr) -{ - size_t before = functionLookup.size (); - expr->accept_vis (*this); - if (functionLookup.size () > before) - { - auto fndecl = functionLookup.back (); - functionLookup.pop_back (); - return fndecl; - } - - rust_error_at (expr->get_locus_slow (), "failed to lookup function"); - return NULL; -} - -void -TypeResolution::visit (AST::Token &tok) -{} - -void -TypeResolution::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -TypeResolution::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -TypeResolution::visit (AST::IdentifierExpr &ident_expr) -{ - AST::Type *type = NULL; - bool ok = scope.LookupType (ident_expr.get_ident (), &type); - if (!ok) - { - rust_error_at (ident_expr.get_locus (), "unknown identifier"); - return; - } - - typeBuffer.push_back (type); -} - -void -TypeResolution::visit (AST::Lifetime &lifetime) -{} - -void -TypeResolution::visit (AST::LifetimeParam &lifetime_param) -{} - -void -TypeResolution::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -TypeResolution::visit (AST::PathInExpression &path) -{ - // look up in the functionScope else lookup in the toplevel scan - AST::Function *fndecl = NULL; - if (scope.LookupFunction (path.as_string (), &fndecl)) - { - functionLookup.push_back (fndecl); - return; - } - - fndecl = toplevel.lookupFunction (&path); - if (fndecl != NULL) - { - functionLookup.push_back (fndecl); - return; - } -} - -void -TypeResolution::visit (AST::TypePathSegment &segment) -{} -void -TypeResolution::visit (AST::TypePathSegmentGeneric &segment) -{} - -void -TypeResolution::visit (AST::TypePathSegmentFunction &segment) -{} - -void -TypeResolution::visit (AST::TypePath &path) -{ - // this may not be robust enough for type comparisons but lets try it for now - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -TypeResolution::visit (AST::QualifiedPathInExpression &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -void -TypeResolution::visit (AST::QualifiedPathInType &path) -{ - typeComparisonBuffer.push_back (path.as_string ()); -} - -// rust-expr.h -void -TypeResolution::visit (AST::LiteralExpr &expr) -{ - std::string type; - switch (expr.get_lit_type ()) - { - case AST::Literal::CHAR: - type = "char"; - break; - - case AST::Literal::STRING: - case AST::Literal::RAW_STRING: - type = "str"; - break; - - case AST::Literal::BOOL: - type = "bool"; - break; - - case AST::Literal::BYTE: - type = "u8"; - break; - - // FIXME these are not always going to be the case - // eg: suffix on the value can change the type - case AST::Literal::FLOAT: - type = "f32"; - break; - - case AST::Literal::INT: - type = "i32"; - break; - - case AST::Literal::BYTE_STRING: - case AST::Literal::RAW_BYTE_STRING: - // FIXME - break; - } - - if (type.empty ()) - { - rust_error_at (expr.get_locus (), "unknown literal: %s", - expr.get_literal ().as_string ().c_str ()); - return; - } - - AST::Type *val = NULL; - bool ok = scope.LookupType (type, &val); - if (ok) - typeBuffer.push_back (val); - else - rust_error_at (expr.get_locus (), "unknown literal type: %s", type.c_str ()); -} - -void -TypeResolution::visit (AST::AttrInputLiteral &attr_input) -{} - -void -TypeResolution::visit (AST::MetaItemLitExpr &meta_item) -{} - -void -TypeResolution::visit (AST::MetaItemPathLit &meta_item) -{} - -void -TypeResolution::visit (AST::BorrowExpr &expr) -{} -void -TypeResolution::visit (AST::DereferenceExpr &expr) -{} -void -TypeResolution::visit (AST::ErrorPropagationExpr &expr) -{} -void -TypeResolution::visit (AST::NegationExpr &expr) -{} - -void -TypeResolution::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - size_t before; - before = typeBuffer.size (); - expr.visit_lhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus (), "unable to determine lhs type"); - return; - } - - auto lhsType = typeBuffer.back (); - typeBuffer.pop_back (); - - before = typeBuffer.size (); - expr.visit_rhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus (), "unable to determine rhs type"); - return; - } - - auto rhsType = typeBuffer.back (); - // not poping because we will be checking they match and the - // scope will require knowledge of the type - - // do the lhsType and the rhsType match - typesAreCompatible (lhsType, rhsType, expr.get_right_expr ()->get_locus_slow ()); -} - -void -TypeResolution::visit (AST::ComparisonExpr &expr) -{} - -void -TypeResolution::visit (AST::LazyBooleanExpr &expr) -{} - -void -TypeResolution::visit (AST::TypeCastExpr &expr) -{} - -void -TypeResolution::visit (AST::AssignmentExpr &expr) -{ - size_t before; - before = typeBuffer.size (); - expr.visit_lhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus (), "unable to determine lhs type"); - return; - } - - auto lhsType = typeBuffer.back (); - typeBuffer.pop_back (); - - before = typeBuffer.size (); - expr.visit_rhs (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_locus (), "unable to determine rhs type"); - return; - } - - auto rhsType = typeBuffer.back (); - // not poping because we will be checking they match and the - // scope will require knowledge of the type - - // do the lhsType and the rhsType match - if (!typesAreCompatible (lhsType, rhsType, - expr.get_right_expr ()->get_locus_slow ())) - return; - - // is the lhs mutable? -} - -void -TypeResolution::visit (AST::CompoundAssignmentExpr &expr) -{} - -void -TypeResolution::visit (AST::GroupedExpr &expr) -{} - -void -TypeResolution::visit (AST::ArrayElemsValues &elems) -{ - // we need to generate the AST::ArrayType for this array init_expression - // we can get the size via get_num_values() but we need to ensure each element - // are type compatible - - bool failed = false; - AST::Type *last_inferred_type = nullptr; - elems.iterate ([&] (AST::Expr *expr) mutable -> bool { - size_t before; - before = typeBuffer.size (); - expr->accept_vis (*this); - if (typeBuffer.size () <= before) - { - rust_error_at (expr->get_locus_slow (), - "unable to determine element type"); - return false; - } - - AST::Type *inferedType = typeBuffer.back (); - typeBuffer.pop_back (); - - if (last_inferred_type == nullptr) - last_inferred_type = inferedType; - else - { - if (!typesAreCompatible (last_inferred_type, inferedType, - expr->get_locus_slow ())) - { - failed = true; - return false; - } - } - - return true; - }); - - // nothing to do when its failed - if (failed) - return; - - // FIXME This will leak - auto capacity - = new AST::LiteralExpr (std::to_string (elems.get_num_values ()), - AST::Literal::INT, - Linemap::predeclared_location ()); - auto arrayType = new AST::ArrayType (last_inferred_type->clone_type (), - std::unique_ptr (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 (new std::string (field.get_field_name ())); - field.get_value ()->accept_vis (*this); -} - -void -TypeResolution::visit (AST::StructExprFieldIndexValue &field) -{ - tupleIndexBuffer = std::unique_ptr (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 ( - new AST::TypePathSegment (::std::move (seg), false, - expr.get_locus_slow ())); - ::std::vector< ::std::unique_ptr > segs; - segs.push_back (::std::move (typePath)); - auto bType - = new AST::TypePath (::std::move (segs), expr.get_locus_slow (), false); - typeBuffer.push_back (bType); -} - -void -TypeResolution::visit (AST::StructExprStructBase &expr) -{} -void -TypeResolution::visit (AST::StructExprTuple &expr) -{} -void -TypeResolution::visit (AST::StructExprUnit &expr) -{} -// void TypeResolution::visit(EnumExprField& field) {} -void -TypeResolution::visit (AST::EnumExprFieldIdentifier &field) -{} -void -TypeResolution::visit (AST::EnumExprFieldIdentifierValue &field) -{} -void -TypeResolution::visit (AST::EnumExprFieldIndexValue &field) -{} -void -TypeResolution::visit (AST::EnumExprStruct &expr) -{} -void -TypeResolution::visit (AST::EnumExprTuple &expr) -{} -void -TypeResolution::visit (AST::EnumExprFieldless &expr) -{} - -void -TypeResolution::visit (AST::CallExpr &expr) -{ - // this look up should probably be moved to name resolution - auto fndecl = lookupFndecl (expr.get_function_expr ().get ()); - if (fndecl == NULL) - return; - - // check num args match - if (fndecl->get_function_params ().size () != expr.get_params ().size ()) - { - rust_error_at (expr.get_locus_slow (), - "differing number of arguments vs parameters to function"); - return; - } - - typeBuffer.push_back (fndecl->get_return_type ().get ()); - expr.fndeclRef = fndecl; - - auto before = typeBuffer.size (); - for (auto &item : expr.get_params ()) - item->accept_vis (*this); - - auto numInferedParams = typeBuffer.size () - before; - if (numInferedParams != expr.get_params ().size ()) - { - rust_error_at (expr.get_locus (), "Failed to infer all parameters"); - return; - } - - auto offs = numInferedParams - 1; - for (auto it = fndecl->get_function_params ().rbegin (); - it != fndecl->get_function_params ().rend (); ++it) - { - AST::Type *argument = typeBuffer.back (); - typeBuffer.pop_back (); - - if (!typesAreCompatible (it->get_type ().get (), argument, - expr.get_params ()[offs]->get_locus_slow ())) - return; - offs--; - } -} - -void -TypeResolution::visit (AST::MethodCallExpr &expr) -{} -void -TypeResolution::visit (AST::FieldAccessExpr &expr) -{} -void -TypeResolution::visit (AST::ClosureExprInner &expr) -{} - -void -TypeResolution::visit (AST::BlockExpr &expr) -{ - scope.Push (); - for (auto &stmt : expr.get_statements ()) - { - stmt->accept_vis (*this); - } - scope.Pop (); -} - -void -TypeResolution::visit (AST::ClosureExprInnerTyped &expr) -{} -void -TypeResolution::visit (AST::ContinueExpr &expr) -{} -void -TypeResolution::visit (AST::BreakExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromToExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromExpr &expr) -{} -void -TypeResolution::visit (AST::RangeToExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFullExpr &expr) -{} -void -TypeResolution::visit (AST::RangeFromToInclExpr &expr) -{} -void -TypeResolution::visit (AST::RangeToInclExpr &expr) -{} - -void -TypeResolution::visit (AST::ReturnExpr &expr) -{ - // Ensure the type of this matches the function - auto before = typeBuffer.size (); - expr.get_returned_expr ()->accept_vis (*this); - - if (typeBuffer.size () <= before) - { - rust_error_at (expr.get_returned_expr ()->get_locus_slow (), - "unable to determine type for return expr"); - return; - } - - auto inferedType = typeBuffer.back (); - typeBuffer.pop_back (); - - // check this is compatible with the return type - // this will again have issues with structs before we move to HIR - - auto function = scope.CurrentFunction (); - if (!function->has_return_type ()) - { - rust_error_at (expr.get_locus (), "return for void function %s", - function->as_string ().c_str ()); - return; - } - - if (!typesAreCompatible (function->get_return_type ().get (), inferedType, - expr.get_locus_slow ())) - { - return; - } -} - -void -TypeResolution::visit (AST::UnsafeBlockExpr &expr) -{} -void -TypeResolution::visit (AST::LoopExpr &expr) -{} -void -TypeResolution::visit (AST::WhileLoopExpr &expr) -{} -void -TypeResolution::visit (AST::WhileLetLoopExpr &expr) -{} -void -TypeResolution::visit (AST::ForLoopExpr &expr) -{} - -void -TypeResolution::visit (AST::IfExpr &expr) -{ - expr.vis_if_block (*this); -} - -void -TypeResolution::visit (AST::IfExprConseqElse &expr) -{ - expr.vis_if_block (*this); - expr.vis_else_block (*this); -} - -void -TypeResolution::visit (AST::IfExprConseqIf &expr) -{ - expr.vis_if_block (*this); - expr.vis_conseq_if_expr (*this); -} - -void -TypeResolution::visit (AST::IfExprConseqIfLet &expr) -{} -void -TypeResolution::visit (AST::IfLetExpr &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqElse &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqIf &expr) -{} -void -TypeResolution::visit (AST::IfLetExprConseqIfLet &expr) -{} -// void TypeResolution::visit(MatchCase& match_case) {} -/*void -TypeResolution::visit (AST::MatchCaseBlockExpr &match_case) -{}*/ -/*void -TypeResolution::visit (AST::MatchCaseExpr &match_case) -{}*/ -void -TypeResolution::visit (AST::MatchExpr &expr) -{} -void -TypeResolution::visit (AST::AwaitExpr &expr) -{} -void -TypeResolution::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -TypeResolution::visit (AST::TypeParam ¶m) -{} -// void TypeResolution::visit(WhereClauseItem& item) {} -void -TypeResolution::visit (AST::LifetimeWhereClauseItem &item) -{} -void -TypeResolution::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -TypeResolution::visit (AST::Method &method) -{} -void -TypeResolution::visit (AST::ModuleBodied &module) -{} -void -TypeResolution::visit (AST::ModuleNoBody &module) -{} -void -TypeResolution::visit (AST::ExternCrate &crate) -{} -// void TypeResolution::visit(UseTree& use_tree) {} -void -TypeResolution::visit (AST::UseTreeGlob &use_tree) -{} -void -TypeResolution::visit (AST::UseTreeList &use_tree) -{} -void -TypeResolution::visit (AST::UseTreeRebind &use_tree) -{} -void -TypeResolution::visit (AST::UseDeclaration &use_decl) -{} - -void -TypeResolution::visit (AST::Function &function) -{ - // always emit the function with return type in the event of nil return type - // its a marker for a void function - scope.InsertType (function.get_function_name (), function.get_return_type ().get ()); - scope.InsertFunction (function.get_function_name (), &function); - scope.PushFunction (&function); - scope.Push (); - - for (auto ¶m : function.get_function_params ()) - { - if (!isTypeInScope (param.get_type ().get (), param.get_locus ())) - { - scope.Pop (); - scope.PopFunction (); - return; - } - - auto before = letPatternBuffer.size (); - param.get_pattern ()->accept_vis (*this); - if (letPatternBuffer.size () <= before) - { - rust_error_at (param.get_locus (), "failed to analyse parameter name"); - - scope.Pop (); - scope.PopFunction (); - return; - } - - auto paramName = letPatternBuffer.back (); - letPatternBuffer.pop_back (); - scope.InsertType (paramName.get_ident (), param.get_type ().get ()); - } - - // ensure the return type is resolved - if (function.has_return_type ()) - { - if (!isTypeInScope (function.get_return_type ().get (), function.get_locus ())) - { - scope.Pop (); - scope.PopFunction (); - return; - } - } - - // walk the expression body - for (auto &stmt : function.get_definition ()->get_statements ()) - { - stmt->accept_vis (*this); - } - - auto localMap = scope.PeekLocals (); - for (auto &[_, value] : localMap) - function.locals.push_back (value); - - scope.Pop (); - scope.PopFunction (); -} - -void -TypeResolution::visit (AST::TypeAlias &type_alias) -{} - -void -TypeResolution::visit (AST::StructStruct &struct_item) -{ - for (auto &field : struct_item.get_fields ()) - { - if (!isTypeInScope (field.get_field_type ().get (), - Linemap::unknown_location ())) - { - rust_fatal_error (Linemap::unknown_location (), - "unknown type in struct field"); - return; - } - } - - scope.InsertStruct (struct_item.get_struct_name (), &struct_item); -} - -void -TypeResolution::visit (AST::TupleStruct &tuple_struct) -{} -void -TypeResolution::visit (AST::EnumItem &item) -{} -void -TypeResolution::visit (AST::EnumItemTuple &item) -{} -void -TypeResolution::visit (AST::EnumItemStruct &item) -{} -void -TypeResolution::visit (AST::EnumItemDiscriminant &item) -{} -void -TypeResolution::visit (AST::Enum &enum_item) -{} -void -TypeResolution::visit (AST::Union &union_item) -{} - -void -TypeResolution::visit (AST::ConstantItem &const_item) -{ - printf ("ConstantItem: %s\n", const_item.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::StaticItem &static_item) -{} -void -TypeResolution::visit (AST::TraitItemFunc &item) -{} -void -TypeResolution::visit (AST::TraitItemMethod &item) -{} -void -TypeResolution::visit (AST::TraitItemConst &item) -{} -void -TypeResolution::visit (AST::TraitItemType &item) -{} -void -TypeResolution::visit (AST::Trait &trait) -{} -void -TypeResolution::visit (AST::InherentImpl &impl) -{} -void -TypeResolution::visit (AST::TraitImpl &impl) -{} -// void TypeResolution::visit(ExternalItem& item) {} -void -TypeResolution::visit (AST::ExternalStaticItem &item) -{} -void -TypeResolution::visit (AST::ExternalFunctionItem &item) -{} -void -TypeResolution::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -TypeResolution::visit (AST::MacroMatchFragment &match) -{} -void -TypeResolution::visit (AST::MacroMatchRepetition &match) -{} -void -TypeResolution::visit (AST::MacroMatcher &matcher) -{} -void -TypeResolution::visit (AST::MacroRulesDefinition &rules_def) -{} -void -TypeResolution::visit (AST::MacroInvocation ¯o_invoc) -{} -void -TypeResolution::visit (AST::MetaItemPath &meta_item) -{} -void -TypeResolution::visit (AST::MetaItemSeq &meta_item) -{} -void -TypeResolution::visit (AST::MetaWord &meta_item) -{} -void -TypeResolution::visit (AST::MetaNameValueStr &meta_item) -{} -void -TypeResolution::visit (AST::MetaListPaths &meta_item) -{} -void -TypeResolution::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -TypeResolution::visit (AST::LiteralPattern &pattern) -{ - printf ("LiteralPattern: %s\n", pattern.as_string ().c_str ()); -} - -void -TypeResolution::visit (AST::IdentifierPattern &pattern) -{ - letPatternBuffer.push_back (pattern); -} - -void -TypeResolution::visit (AST::WildcardPattern &pattern) -{} -// void TypeResolution::visit(RangePatternBound& bound) {} -void -TypeResolution::visit (AST::RangePatternBoundLiteral &bound) -{} -void -TypeResolution::visit (AST::RangePatternBoundPath &bound) -{} -void -TypeResolution::visit (AST::RangePatternBoundQualPath &bound) -{} -void -TypeResolution::visit (AST::RangePattern &pattern) -{} -void -TypeResolution::visit (AST::ReferencePattern &pattern) -{} -// void TypeResolution::visit(StructPatternField& field) {} -void -TypeResolution::visit (AST::StructPatternFieldTuplePat &field) -{} -void -TypeResolution::visit (AST::StructPatternFieldIdentPat &field) -{} -void -TypeResolution::visit (AST::StructPatternFieldIdent &field) -{} -void -TypeResolution::visit (AST::StructPattern &pattern) -{} -// void TypeResolution::visit(TupleStructItems& tuple_items) {} -void -TypeResolution::visit (AST::TupleStructItemsNoRange &tuple_items) -{} -void -TypeResolution::visit (AST::TupleStructItemsRange &tuple_items) -{} -void -TypeResolution::visit (AST::TupleStructPattern &pattern) -{} -// void TypeResolution::visit(TuplePatternItems& tuple_items) {} -void -TypeResolution::visit (AST::TuplePatternItemsMultiple &tuple_items) -{} -void -TypeResolution::visit (AST::TuplePatternItemsRanged &tuple_items) -{} -void -TypeResolution::visit (AST::TuplePattern &pattern) -{} -void -TypeResolution::visit (AST::GroupedPattern &pattern) -{} -void -TypeResolution::visit (AST::SlicePattern &pattern) -{} - -// rust-stmt.h -void -TypeResolution::visit (AST::EmptyStmt &stmt) -{} - -void -TypeResolution::visit (AST::LetStmt &stmt) -{ - scope.InsertLocal (stmt.as_string (), &stmt); - if (!stmt.has_init_expr () && !stmt.has_type ()) - { - rust_error_at (stmt.get_locus (), - "E0282: type annotations or init expression needed"); - return; - } - - AST::Type *inferedType = nullptr; - if (stmt.has_init_expr ()) - { - auto before = typeBuffer.size (); - stmt.get_init_expr ()->accept_vis (*this); - - if (typeBuffer.size () <= before) - { - rust_error_at ( - stmt.get_init_expr ()->get_locus_slow (), - "unable to determine type for declaration from init expr"); - return; - } - - inferedType = typeBuffer.back (); - typeBuffer.pop_back (); - - if (inferedType == NULL) - { - rust_error_at (stmt.get_init_expr ()->get_locus_slow (), - "void type found for statement initialisation"); - return; - } - } - - if (stmt.has_type () && stmt.has_init_expr ()) - { - if (!typesAreCompatible (stmt.get_type ().get (), inferedType, - stmt.get_init_expr ()->get_locus_slow ())) - { - return; - } - } - else if (stmt.has_type ()) - { - auto before = typeComparisonBuffer.size (); - stmt.get_type ()->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (stmt.get_locus (), "failed to understand type for lhs"); - return; - } - auto typeString = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - // AST::Type *val = NULL; - // if (!scope.LookupType (typeString, &val)) - // { - // rust_error_at (stmt.locus, "LetStmt has unknown type: %s", - // stmt.type->as_string ().c_str ()); - // return; - // } - } - else if (inferedType != nullptr) - { - auto before = typeComparisonBuffer.size (); - inferedType->accept_vis (*this); - if (typeComparisonBuffer.size () <= before) - { - rust_error_at (stmt.get_locus (), "failed to understand type for lhs"); - return; - } - auto typeString = typeComparisonBuffer.back (); - typeComparisonBuffer.pop_back (); - - // AST::Type *val = NULL; - // if (!scope.LookupType (typeString, &val)) - // { - // rust_error_at (stmt.get_locus (), "Inferred unknown type: %s", - // inferedType->as_string ().c_str ()); - // return; - // } - } - else - { - rust_fatal_error (stmt.get_locus (), "Failed to determine any type for LetStmt"); - return; - } - - // ensure the decl has the type set for compilation later on - if (!stmt.has_type ()) - { - stmt.inferedType = inferedType; - } - - // get all the names part of this declaration and add the types to the scope - stmt.get_pattern ()->accept_vis (*this); - for (auto &pattern : letPatternBuffer) - scope.InsertType (pattern.get_ident (), inferedType); - - letPatternBuffer.clear (); -} - -void -TypeResolution::visit (AST::ExprStmtWithoutBlock &stmt) -{ - stmt.get_expr ()->accept_vis (*this); -} - -void -TypeResolution::visit (AST::ExprStmtWithBlock &stmt) -{ - scope.Push (); - stmt.get_expr ()->accept_vis (*this); - auto localMap = scope.PeekLocals (); - for (auto &[_, value] : localMap) - { - stmt.locals.push_back (value); - } - scope.Pop (); -} - -// rust-type.h -void -TypeResolution::visit (AST::TraitBound &bound) -{} - -void -TypeResolution::visit (AST::ImplTraitType &type) -{} - -void -TypeResolution::visit (AST::TraitObjectType &type) -{} -void -TypeResolution::visit (AST::ParenthesisedType &type) -{} -void -TypeResolution::visit (AST::ImplTraitTypeOneBound &type) -{} -void -TypeResolution::visit (AST::TraitObjectTypeOneBound &type) -{} -void -TypeResolution::visit (AST::TupleType &type) -{} -void -TypeResolution::visit (AST::NeverType &type) -{} -void -TypeResolution::visit (AST::RawPointerType &type) -{} -void -TypeResolution::visit (AST::ReferenceType &type) -{} - -void -TypeResolution::visit (AST::ArrayType &type) -{ - typeComparisonBuffer.push_back (type.get_elem_type ()->as_string ()); -} - -void -TypeResolution::visit (AST::SliceType &type) -{} -void -TypeResolution::visit (AST::InferredType &type) -{} -void -TypeResolution::visit (AST::BareFunctionType &type) -{} - -} // namespace Analysis -} // namespace Rust diff --git a/gcc/rust/analysis/rust-type-resolution.h b/gcc/rust/analysis/rust-type-resolution.h deleted file mode 100644 index 2f61a39..0000000 --- a/gcc/rust/analysis/rust-type-resolution.h +++ /dev/null @@ -1,334 +0,0 @@ -// Copyright (C) 2020 Free Software Foundation, Inc. - -// This file is part of GCC. - -// GCC is free software; you can redistribute it and/or modify it under -// the terms of the GNU General Public License as published by the Free -// Software Foundation; either version 3, or (at your option) any later -// version. - -// GCC is distributed in the hope that it will be useful, but WITHOUT ANY -// WARRANTY; without even the implied warranty of MERCHANTABILITY or -// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License -// for more details. - -// You should have received a copy of the GNU General Public License -// along with GCC; see the file COPYING3. If not see -// . -#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 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 functionStack; - - Scope functionScope; - Scope localsPerBlock; - Scope structsPerBlock; - Scope typeScope; -}; - -class TypeResolution : public Resolution -{ - friend class TypeScoping; - -public: - ~TypeResolution (); - static bool Resolve (AST::Crate &crate, TopLevelScan &toplevel); - - // visitor impl - // rust-ast.h - // void visit(AttrInput& attr_input); - // void visit(TokenTree& token_tree); - // void visit(MacroMatch& macro_match); - void visit (AST::Token &tok) override; - void visit (AST::DelimTokenTree &delim_tok_tree) override; - void visit (AST::AttrInputMetaItemContainer &input) override; - // void visit(MetaItem& meta_item) override; - // void vsit(Stmt& stmt) override; - // void visit(Expr& expr) override; - void visit (AST::IdentifierExpr &ident_expr) override; - // void visit(Pattern& pattern) override; - // void visit(Type& type) override; - // void visit(TypeParamBound& type_param_bound) override; - void visit (AST::Lifetime &lifetime) override; - // void visit(GenericParam& generic_param) override; - void visit (AST::LifetimeParam &lifetime_param) override; - // void visit(TraitItem& trait_item) override; - // void visit(InherentImplItem& inherent_impl_item) override; - // void visit(TraitImplItem& trait_impl_item) override; - void visit (AST::MacroInvocationSemi ¯o) override; - - // rust-path.h - void visit (AST::PathInExpression &path) override; - void visit (AST::TypePathSegment &segment) override; - void visit (AST::TypePathSegmentGeneric &segment) override; - void visit (AST::TypePathSegmentFunction &segment) override; - void visit (AST::TypePath &path) override; - void visit (AST::QualifiedPathInExpression &path) override; - void visit (AST::QualifiedPathInType &path) override; - - // rust-expr.h - void visit (AST::LiteralExpr &expr) override; - void visit (AST::AttrInputLiteral &attr_input) override; - void visit (AST::MetaItemLitExpr &meta_item) override; - void visit (AST::MetaItemPathLit &meta_item) override; - void visit (AST::BorrowExpr &expr) override; - void visit (AST::DereferenceExpr &expr) override; - void visit (AST::ErrorPropagationExpr &expr) override; - void visit (AST::NegationExpr &expr) override; - void visit (AST::ArithmeticOrLogicalExpr &expr) override; - void visit (AST::ComparisonExpr &expr) override; - void visit (AST::LazyBooleanExpr &expr) override; - void visit (AST::TypeCastExpr &expr) override; - void visit (AST::AssignmentExpr &expr) override; - void visit (AST::CompoundAssignmentExpr &expr) override; - void visit (AST::GroupedExpr &expr) override; - // void visit(ArrayElems& elems) override; - void visit (AST::ArrayElemsValues &elems) override; - void visit (AST::ArrayElemsCopied &elems) override; - void visit (AST::ArrayExpr &expr) override; - void visit (AST::ArrayIndexExpr &expr) override; - void visit (AST::TupleExpr &expr) override; - void visit (AST::TupleIndexExpr &expr) override; - void visit (AST::StructExprStruct &expr) override; - // void visit(StructExprField& field) override; - void visit (AST::StructExprFieldIdentifier &field) override; - void visit (AST::StructExprFieldIdentifierValue &field) override; - void visit (AST::StructExprFieldIndexValue &field) override; - void visit (AST::StructExprStructFields &expr) override; - void visit (AST::StructExprStructBase &expr) override; - void visit (AST::StructExprTuple &expr) override; - void visit (AST::StructExprUnit &expr) override; - // void visit(EnumExprField& field) override; - void visit (AST::EnumExprFieldIdentifier &field) override; - void visit (AST::EnumExprFieldIdentifierValue &field) override; - void visit (AST::EnumExprFieldIndexValue &field) override; - void visit (AST::EnumExprStruct &expr) override; - void visit (AST::EnumExprTuple &expr) override; - void visit (AST::EnumExprFieldless &expr) override; - void visit (AST::CallExpr &expr) override; - void visit (AST::MethodCallExpr &expr) override; - void visit (AST::FieldAccessExpr &expr) override; - void visit (AST::ClosureExprInner &expr) override; - void visit (AST::BlockExpr &expr) override; - void visit (AST::ClosureExprInnerTyped &expr) override; - void visit (AST::ContinueExpr &expr) override; - void visit (AST::BreakExpr &expr) override; - void visit (AST::RangeFromToExpr &expr) override; - void visit (AST::RangeFromExpr &expr) override; - void visit (AST::RangeToExpr &expr) override; - void visit (AST::RangeFullExpr &expr) override; - void visit (AST::RangeFromToInclExpr &expr) override; - void visit (AST::RangeToInclExpr &expr) override; - void visit (AST::ReturnExpr &expr) override; - void visit (AST::UnsafeBlockExpr &expr) override; - void visit (AST::LoopExpr &expr) override; - void visit (AST::WhileLoopExpr &expr) override; - void visit (AST::WhileLetLoopExpr &expr) override; - void visit (AST::ForLoopExpr &expr) override; - void visit (AST::IfExpr &expr) override; - void visit (AST::IfExprConseqElse &expr) override; - void visit (AST::IfExprConseqIf &expr) override; - void visit (AST::IfExprConseqIfLet &expr) override; - void visit (AST::IfLetExpr &expr) override; - void visit (AST::IfLetExprConseqElse &expr) override; - void visit (AST::IfLetExprConseqIf &expr) override; - void visit (AST::IfLetExprConseqIfLet &expr) override; - // void visit(MatchCase& match_case) override; - // void visit (AST::MatchCaseBlockExpr &match_case) override; - // void visit (AST::MatchCaseExpr &match_case) override; - void visit (AST::MatchExpr &expr) override; - void visit (AST::AwaitExpr &expr) override; - void visit (AST::AsyncBlockExpr &expr) override; - - // rust-item.h - void visit (AST::TypeParam ¶m) override; - // void visit(WhereClauseItem& item) override; - void visit (AST::LifetimeWhereClauseItem &item) override; - void visit (AST::TypeBoundWhereClauseItem &item) override; - void visit (AST::Method &method) override; - void visit (AST::ModuleBodied &module) override; - void visit (AST::ModuleNoBody &module) override; - void visit (AST::ExternCrate &crate) override; - // void visit(UseTree& use_tree) override; - void visit (AST::UseTreeGlob &use_tree) override; - void visit (AST::UseTreeList &use_tree) override; - void visit (AST::UseTreeRebind &use_tree) override; - void visit (AST::UseDeclaration &use_decl) override; - void visit (AST::Function &function) override; - void visit (AST::TypeAlias &type_alias) override; - void visit (AST::StructStruct &struct_item) override; - void visit (AST::TupleStruct &tuple_struct) override; - void visit (AST::EnumItem &item) override; - void visit (AST::EnumItemTuple &item) override; - void visit (AST::EnumItemStruct &item) override; - void visit (AST::EnumItemDiscriminant &item) override; - void visit (AST::Enum &enum_item) override; - void visit (AST::Union &union_item) override; - void visit (AST::ConstantItem &const_item) override; - void visit (AST::StaticItem &static_item) override; - void visit (AST::TraitItemFunc &item) override; - void visit (AST::TraitItemMethod &item) override; - void visit (AST::TraitItemConst &item) override; - void visit (AST::TraitItemType &item) override; - void visit (AST::Trait &trait) override; - void visit (AST::InherentImpl &impl) override; - void visit (AST::TraitImpl &impl) override; - // void visit(ExternalItem& item) override; - void visit (AST::ExternalStaticItem &item) override; - void visit (AST::ExternalFunctionItem &item) override; - void visit (AST::ExternBlock &block) override; - - // rust-macro.h - void visit (AST::MacroMatchFragment &match) override; - void visit (AST::MacroMatchRepetition &match) override; - void visit (AST::MacroMatcher &matcher) override; - void visit (AST::MacroRulesDefinition &rules_def) override; - void visit (AST::MacroInvocation ¯o_invoc) override; - void visit (AST::MetaItemPath &meta_item) override; - void visit (AST::MetaItemSeq &meta_item) override; - void visit (AST::MetaWord &meta_item) override; - void visit (AST::MetaNameValueStr &meta_item) override; - void visit (AST::MetaListPaths &meta_item) override; - void visit (AST::MetaListNameValueStr &meta_item) override; - - // rust-pattern.h - void visit (AST::LiteralPattern &pattern) override; - void visit (AST::IdentifierPattern &pattern) override; - void visit (AST::WildcardPattern &pattern) override; - // void visit(RangePatternBound& bound) override; - void visit (AST::RangePatternBoundLiteral &bound) override; - void visit (AST::RangePatternBoundPath &bound) override; - void visit (AST::RangePatternBoundQualPath &bound) override; - void visit (AST::RangePattern &pattern) override; - void visit (AST::ReferencePattern &pattern) override; - // void visit(StructPatternField& field) override; - void visit (AST::StructPatternFieldTuplePat &field) override; - void visit (AST::StructPatternFieldIdentPat &field) override; - void visit (AST::StructPatternFieldIdent &field) override; - void visit (AST::StructPattern &pattern) override; - // void visit(TupleStructItems& tuple_items) override; - void visit (AST::TupleStructItemsNoRange &tuple_items) override; - void visit (AST::TupleStructItemsRange &tuple_items) override; - void visit (AST::TupleStructPattern &pattern) override; - // void visit(TuplePatternItems& tuple_items) override; - void visit (AST::TuplePatternItemsMultiple &tuple_items) override; - void visit (AST::TuplePatternItemsRanged &tuple_items) override; - void visit (AST::TuplePattern &pattern) override; - void visit (AST::GroupedPattern &pattern) override; - void visit (AST::SlicePattern &pattern) override; - - // rust-stmt.h - void visit (AST::EmptyStmt &stmt) override; - void visit (AST::LetStmt &stmt) override; - void visit (AST::ExprStmtWithoutBlock &stmt) override; - void visit (AST::ExprStmtWithBlock &stmt) override; - - // rust-type.h - void visit (AST::TraitBound &bound) override; - void visit (AST::ImplTraitType &type) override; - void visit (AST::TraitObjectType &type) override; - void visit (AST::ParenthesisedType &type) override; - void visit (AST::ImplTraitTypeOneBound &type) override; - void visit (AST::TraitObjectTypeOneBound &type) override; - void visit (AST::TupleType &type) override; - void visit (AST::NeverType &type) override; - void visit (AST::RawPointerType &type) override; - void visit (AST::ReferenceType &type) override; - void visit (AST::ArrayType &type) override; - void visit (AST::SliceType &type) override; - void visit (AST::InferredType &type) override; - void visit (AST::BareFunctionType &type) override; - -private: - TypeResolution (AST::Crate &crate, TopLevelScan &toplevel); - bool go () override; - bool typesAreCompatible (AST::Type *lhs, AST::Type *rhs, Location locus); - AST::Function *lookupFndecl (AST::Expr *expr); - bool isTypeInScope (AST::Type *type, Location locus); - - TypeScoping scope; - std::unique_ptr identifierBuffer; - std::unique_ptr 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 -// . - -#ifndef RUST_TYPE_VISITOR_H -#define RUST_TYPE_VISITOR_H - -#include "rust-system.h" -#include "rust-ast-full.h" -#include "rust-ast-visitor.h" -#include "rust-scan.h" - -namespace Rust { -namespace Analysis { - -class BaseTypeVisitor : public AST::ASTVisitor -{ -public: - // visitor impl - // rust-ast.h - // virtual void visit(AttrInput& attr_input); - // virtual void visit(TokenTree& token_tree); - // virtual void visit(MacroMatch& macro_match); - virtual void visit (AST::Token &tok) override {} - virtual void visit (AST::DelimTokenTree &delim_tok_tree) override {} - virtual void visit (AST::AttrInputMetaItemContainer &input) override {} - // virtual void visit(MetaItem& meta_item) override {} - // void vsit(Stmt& stmt) override {} - // virtual void visit(Expr& expr) override {} - virtual void visit (AST::IdentifierExpr &ident_expr) override {} - // virtual void visit(Pattern& pattern) override {} - // virtual void visit(Type& type) override {} - // virtual void visit(TypeParamBound& type_param_bound) override {} - virtual void visit (AST::Lifetime &lifetime) override {} - // virtual void visit(GenericParam& generic_param) override {} - virtual void visit (AST::LifetimeParam &lifetime_param) override {} - // virtual void visit(TraitItem& trait_item) override {} - // virtual void visit(InherentImplItem& inherent_impl_item) override {} - // virtual void visit(TraitImplItem& trait_impl_item) override {} - virtual void visit (AST::MacroInvocationSemi ¯o) override {} - - // rust-path.h - virtual void visit (AST::PathInExpression &path) override {} - virtual void visit (AST::TypePathSegment &segment) override {} - virtual void visit (AST::TypePathSegmentGeneric &segment) override {} - virtual void visit (AST::TypePathSegmentFunction &segment) override {} - virtual void visit (AST::TypePath &path) override {} - virtual void visit (AST::QualifiedPathInExpression &path) override {} - virtual void visit (AST::QualifiedPathInType &path) override {} - - // rust-expr.h - virtual void visit (AST::LiteralExpr &expr) override {} - virtual void visit (AST::AttrInputLiteral &attr_input) override {} - virtual void visit (AST::MetaItemLitExpr &meta_item) override {} - virtual void visit (AST::MetaItemPathLit &meta_item) override {} - virtual void visit (AST::BorrowExpr &expr) override {} - virtual void visit (AST::DereferenceExpr &expr) override {} - virtual void visit (AST::ErrorPropagationExpr &expr) override {} - virtual void visit (AST::NegationExpr &expr) override {} - virtual void visit (AST::ArithmeticOrLogicalExpr &expr) override {} - virtual void visit (AST::ComparisonExpr &expr) override {} - virtual void visit (AST::LazyBooleanExpr &expr) override {} - virtual void visit (AST::TypeCastExpr &expr) override {} - virtual void visit (AST::AssignmentExpr &expr) override {} - virtual void visit (AST::CompoundAssignmentExpr &expr) override {} - virtual void visit (AST::GroupedExpr &expr) override {} - // virtual void visit(ArrayElems& elems) override {} - virtual void visit (AST::ArrayElemsValues &elems) override {} - virtual void visit (AST::ArrayElemsCopied &elems) override {} - virtual void visit (AST::ArrayExpr &expr) override {} - virtual void visit (AST::ArrayIndexExpr &expr) override {} - virtual void visit (AST::TupleExpr &expr) override {} - virtual void visit (AST::TupleIndexExpr &expr) override {} - virtual void visit (AST::StructExprStruct &expr) override {} - // virtual void visit(StructExprField& field) override {} - virtual void visit (AST::StructExprFieldIdentifier &field) override {} - virtual void visit (AST::StructExprFieldIdentifierValue &field) override {} - virtual void visit (AST::StructExprFieldIndexValue &field) override {} - virtual void visit (AST::StructExprStructFields &expr) override {} - virtual void visit (AST::StructExprStructBase &expr) override {} - virtual void visit (AST::StructExprTuple &expr) override {} - virtual void visit (AST::StructExprUnit &expr) override {} - // virtual void visit(EnumExprField& field) override {} - virtual void visit (AST::EnumExprFieldIdentifier &field) override {} - virtual void visit (AST::EnumExprFieldIdentifierValue &field) override {} - virtual void visit (AST::EnumExprFieldIndexValue &field) override {} - virtual void visit (AST::EnumExprStruct &expr) override {} - virtual void visit (AST::EnumExprTuple &expr) override {} - virtual void visit (AST::EnumExprFieldless &expr) override {} - virtual void visit (AST::CallExpr &expr) override {} - virtual void visit (AST::MethodCallExpr &expr) override {} - virtual void visit (AST::FieldAccessExpr &expr) override {} - virtual void visit (AST::ClosureExprInner &expr) override {} - virtual void visit (AST::BlockExpr &expr) override {} - virtual void visit (AST::ClosureExprInnerTyped &expr) override {} - virtual void visit (AST::ContinueExpr &expr) override {} - virtual void visit (AST::BreakExpr &expr) override {} - virtual void visit (AST::RangeFromToExpr &expr) override {} - virtual void visit (AST::RangeFromExpr &expr) override {} - virtual void visit (AST::RangeToExpr &expr) override {} - virtual void visit (AST::RangeFullExpr &expr) override {} - virtual void visit (AST::RangeFromToInclExpr &expr) override {} - virtual void visit (AST::RangeToInclExpr &expr) override {} - virtual void visit (AST::ReturnExpr &expr) override {} - virtual void visit (AST::UnsafeBlockExpr &expr) override {} - virtual void visit (AST::LoopExpr &expr) override {} - virtual void visit (AST::WhileLoopExpr &expr) override {} - virtual void visit (AST::WhileLetLoopExpr &expr) override {} - virtual void visit (AST::ForLoopExpr &expr) override {} - virtual void visit (AST::IfExpr &expr) override {} - virtual void visit (AST::IfExprConseqElse &expr) override {} - virtual void visit (AST::IfExprConseqIf &expr) override {} - virtual void visit (AST::IfExprConseqIfLet &expr) override {} - virtual void visit (AST::IfLetExpr &expr) override {} - virtual void visit (AST::IfLetExprConseqElse &expr) override {} - virtual void visit (AST::IfLetExprConseqIf &expr) override {} - virtual void visit (AST::IfLetExprConseqIfLet &expr) override {} - // virtual void visit(MatchCase& match_case) override {} - // virtual void visit (AST::MatchCaseBlockExpr &match_case) override {} - // virtual void visit (AST::MatchCaseExpr &match_case) override {} - virtual void visit (AST::MatchExpr &expr) override {} - virtual void visit (AST::AwaitExpr &expr) override {} - virtual void visit (AST::AsyncBlockExpr &expr) override {} - - // rust-item.h - virtual void visit (AST::TypeParam ¶m) override {} - // virtual void visit(WhereClauseItem& item) override {} - virtual void visit (AST::LifetimeWhereClauseItem &item) override {} - virtual void visit (AST::TypeBoundWhereClauseItem &item) override {} - virtual void visit (AST::Method &method) override {} - virtual void visit (AST::ModuleBodied &module) override {} - virtual void visit (AST::ModuleNoBody &module) override {} - virtual void visit (AST::ExternCrate &crate) override {} - // virtual void visit(UseTree& use_tree) override {} - virtual void visit (AST::UseTreeGlob &use_tree) override {} - virtual void visit (AST::UseTreeList &use_tree) override {} - virtual void visit (AST::UseTreeRebind &use_tree) override {} - virtual void visit (AST::UseDeclaration &use_decl) override {} - virtual void visit (AST::Function &function) override {} - virtual void visit (AST::TypeAlias &type_alias) override {} - virtual void visit (AST::StructStruct &struct_item) override {} - virtual void visit (AST::TupleStruct &tuple_struct) override {} - virtual void visit (AST::EnumItem &item) override {} - virtual void visit (AST::EnumItemTuple &item) override {} - virtual void visit (AST::EnumItemStruct &item) override {} - virtual void visit (AST::EnumItemDiscriminant &item) override {} - virtual void visit (AST::Enum &enum_item) override {} - virtual void visit (AST::Union &union_item) override {} - virtual void visit (AST::ConstantItem &const_item) override {} - virtual void visit (AST::StaticItem &static_item) override {} - virtual void visit (AST::TraitItemFunc &item) override {} - virtual void visit (AST::TraitItemMethod &item) override {} - virtual void visit (AST::TraitItemConst &item) override {} - virtual void visit (AST::TraitItemType &item) override {} - virtual void visit (AST::Trait &trait) override {} - virtual void visit (AST::InherentImpl &impl) override {} - virtual void visit (AST::TraitImpl &impl) override {} - // virtual void visit(ExternalItem& item) override {} - virtual void visit (AST::ExternalStaticItem &item) override {} - virtual void visit (AST::ExternalFunctionItem &item) override {} - virtual void visit (AST::ExternBlock &block) override {} - - // rust-macro.h - virtual void visit (AST::MacroMatchFragment &match) override {} - virtual void visit (AST::MacroMatchRepetition &match) override {} - virtual void visit (AST::MacroMatcher &matcher) override {} - virtual void visit (AST::MacroRulesDefinition &rules_def) override {} - virtual void visit (AST::MacroInvocation ¯o_invoc) override {} - virtual void visit (AST::MetaItemPath &meta_item) override {} - virtual void visit (AST::MetaItemSeq &meta_item) override {} - virtual void visit (AST::MetaWord &meta_item) override {} - virtual void visit (AST::MetaNameValueStr &meta_item) override {} - virtual void visit (AST::MetaListPaths &meta_item) override {} - virtual void visit (AST::MetaListNameValueStr &meta_item) override {} - - // rust-pattern.h - virtual void visit (AST::LiteralPattern &pattern) override {} - virtual void visit (AST::IdentifierPattern &pattern) override {} - virtual void visit (AST::WildcardPattern &pattern) override {} - // virtual void visit(RangePatternBound& bound) override {} - virtual void visit (AST::RangePatternBoundLiteral &bound) override {} - virtual void visit (AST::RangePatternBoundPath &bound) override {} - virtual void visit (AST::RangePatternBoundQualPath &bound) override {} - virtual void visit (AST::RangePattern &pattern) override {} - virtual void visit (AST::ReferencePattern &pattern) override {} - // virtual void visit(StructPatternField& field) override {} - virtual void visit (AST::StructPatternFieldTuplePat &field) override {} - virtual void visit (AST::StructPatternFieldIdentPat &field) override {} - virtual void visit (AST::StructPatternFieldIdent &field) override {} - virtual void visit (AST::StructPattern &pattern) override {} - // virtual void visit(TupleStructItems& tuple_items) override {} - virtual void visit (AST::TupleStructItemsNoRange &tuple_items) override {} - virtual void visit (AST::TupleStructItemsRange &tuple_items) override {} - virtual void visit (AST::TupleStructPattern &pattern) override {} - // virtual void visit(TuplePatternItems& tuple_items) override {} - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) override {} - virtual void visit (AST::TuplePatternItemsRanged &tuple_items) override {} - virtual void visit (AST::TuplePattern &pattern) override {} - virtual void visit (AST::GroupedPattern &pattern) override {} - virtual void visit (AST::SlicePattern &pattern) override {} - - // rust-stmt.h - virtual void visit (AST::EmptyStmt &stmt) override {} - virtual void visit (AST::LetStmt &stmt) override {} - virtual void visit (AST::ExprStmtWithoutBlock &stmt) override {} - virtual void visit (AST::ExprStmtWithBlock &stmt) override {} - - // rust-type.h - virtual void visit (AST::TraitBound &bound) override {} - virtual void visit (AST::ImplTraitType &type) override {} - virtual void visit (AST::TraitObjectType &type) override {} - virtual void visit (AST::ParenthesisedType &type) override {} - virtual void visit (AST::ImplTraitTypeOneBound &type) override {} - virtual void visit (AST::TraitObjectTypeOneBound &type) override {} - virtual void visit (AST::TupleType &type) override {} - virtual void visit (AST::NeverType &type) override {} - virtual void visit (AST::RawPointerType &type) override {} - virtual void visit (AST::ReferenceType &type) override {} - virtual void visit (AST::ArrayType &type) override {} - virtual void visit (AST::SliceType &type) override {} - virtual void visit (AST::InferredType &type) override {} - virtual void visit (AST::BareFunctionType &type) override {} -}; - -class ArrayTypeVisitor : public BaseTypeVisitor -{ -public: - static AST::ArrayType *Resolve (AST::Type *type) - { - ArrayTypeVisitor vis; - type->accept_vis (vis); - return vis.resolved; - } - - virtual void visit (AST::ArrayType &type) override { resolved = &type; }; - -private: - ArrayTypeVisitor () : resolved (nullptr) {} - - AST::ArrayType *resolved; -}; - -} // namespace Analysis -} // namespace Rust - -#endif // RUST_TYPE_VISITOR_H diff --git a/gcc/rust/backend/rust-compile.cc b/gcc/rust/backend/rust-compile.cc index 300240f..a4b5cd4 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -1,1500 +1,31 @@ -#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 &vars) -{ - AST::Type *type = stmt->has_type () ? stmt->get_type ().get () : stmt->inferedType; - translatedType = NULL; - type->accept_vis (*this); - if (translatedType == NULL) - { - rust_error_at (stmt->get_locus (), "failed to compile type for var decl"); - return false; - } - - stmt->get_pattern ()->accept_vis (*this); - for (auto &pattern : patternBuffer) - { - auto var = backend->local_variable (fndecl, pattern.get_ident (), - translatedType, NULL /*decl_var*/, - false /*address_taken*/, stmt->get_locus ()); - vars.push_back (var); - scope.InsertVar (pattern.get_ident (), var); - } - patternBuffer.clear (); - return true; -} - -Bexpression * -Compilation::compileBooleanLiteral (std::string val) -{ - bool bval = val.compare ("true") == 0; - return backend->boolean_constant_expression (bval); -} - -Bexpression * -Compilation::compileFloatLiteral (std::string val, Location locus) -{ - Btype *type = NULL; - bool ok = scope.LookupType ("f32", &type); - if (!ok) - { - rust_fatal_error (locus, "unable to find type"); - return NULL; - } - mpfr_t fval; - if (mpfr_init_set_str (fval, val.c_str (), 10, GMP_RNDN) != 0) - { - rust_fatal_error (locus, "bad number in literal"); - return NULL; - } - return backend->float_constant_expression (type, fval); -} - -Bexpression * -Compilation::compileIntegerLiteral (std::string val, Location locus) -{ - Btype *type = NULL; - bool ok = scope.LookupType ("i32", &type); - if (!ok) - { - rust_fatal_error (locus, "unable to find type"); - return NULL; - } - mpz_t ival; - if (mpz_init_set_str (ival, val.c_str (), 10) != 0) - { - rust_fatal_error (locus, "bad number in literal"); - return NULL; - } - return backend->integer_constant_expression (type, ival); -} - -void -Compilation::visit (AST::Token &tok) -{} - -void -Compilation::visit (AST::DelimTokenTree &delim_tok_tree) -{} - -void -Compilation::visit (AST::AttrInputMetaItemContainer &input) -{} - -void -Compilation::visit (AST::IdentifierExpr &ident_expr) -{ - Bvariable *var = NULL; - if (!scope.LookupVar (ident_expr.as_string (), &var)) - { - rust_fatal_error (ident_expr.get_locus (), "unknown var"); - return; - } - exprs.push_back (backend->var_expression (var, ident_expr.get_locus ())); -} - -void -Compilation::visit (AST::Lifetime &lifetime) -{} - -void -Compilation::visit (AST::LifetimeParam &lifetime_param) -{} - -void -Compilation::visit (AST::MacroInvocationSemi ¯o) -{} - -// rust-path.h -void -Compilation::visit (AST::PathInExpression &path) -{ - Bfunction *fn = NULL; - if (scope.LookupFunction (path.as_string (), &fn)) - { - auto expr - = backend->function_code_expression (fn, path.get_locus ()); - exprs.push_back (expr); - translatedType = scope.GetFnRetType (fn); - return; - } -} - -void -Compilation::visit (AST::TypePathSegment &segment) -{} -void -Compilation::visit (AST::TypePathSegmentGeneric &segment) -{} -void -Compilation::visit (AST::TypePathSegmentFunction &segment) -{} - -void -Compilation::visit (AST::TypePath &path) -{ - if (path.get_segments ().size () > 1) - { - rust_error_at (path.get_locus (), "unable to compile multi segment types yet"); - return; - } - - Btype *type = NULL; - if (!scope.LookupType (path.as_string (), &type)) - { - rust_error_at (path.get_locus (), "unknown type"); - return; - } - translatedType = type; -} - -void -Compilation::visit (AST::QualifiedPathInExpression &path) -{} -void -Compilation::visit (AST::QualifiedPathInType &path) -{} - -// rust-expr.h -void -Compilation::visit (AST::LiteralExpr &expr) -{ - Bexpression *compiled; - switch (expr.get_lit_type ()) - { - case AST::Literal::BOOL: - compiled = compileBooleanLiteral (expr.as_string ()); - break; - - case AST::Literal::FLOAT: - compiled - = compileFloatLiteral (expr.as_string (), expr.get_locus ()); - break; - - case AST::Literal::INT: - compiled - = compileIntegerLiteral (expr.as_string (), expr.get_locus ()); - break; - - default: - rust_fatal_error (expr.get_locus (), "unknown literal"); - return; - } - - exprs.push_back (compiled); -} - -void -Compilation::visit (AST::AttrInputLiteral &attr_input) -{} -void -Compilation::visit (AST::MetaItemLitExpr &meta_item) -{} -void -Compilation::visit (AST::MetaItemPathLit &meta_item) -{} -void -Compilation::visit (AST::BorrowExpr &expr) -{} -void -Compilation::visit (AST::DereferenceExpr &expr) -{} -void -Compilation::visit (AST::ErrorPropagationExpr &expr) -{} - -void -Compilation::visit (AST::NegationExpr &expr) -{ - Bexpression *root = NULL; - VISIT_POP (expr.get_negated_expr ()->get_locus_slow (), expr.get_negated_expr ().get (), root, - exprs); - if (root == NULL) - { - rust_error_at (expr.get_negated_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Operator op; - switch (expr.get_negation_type ()) - { - case AST::NegationExpr::NEGATE: - op = OPERATOR_MINUS; - break; - case AST::NegationExpr::NOT: - op = OPERATOR_NOT; - break; - default: - rust_fatal_error (expr.get_locus (), "failed to compile operator"); - return; - } - - auto unary = backend->unary_expression (op, root, expr.get_locus ()); - exprs.push_back (unary); -} - -void -Compilation::visit (AST::ArithmeticOrLogicalExpr &expr) -{ - Bexpression *lhs = NULL; - VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); - if (lhs == NULL) - { - rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Bexpression *rhs = NULL; - VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); - if (rhs == NULL) - { - rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Operator op; - switch (expr.get_expr_type ()) - { - case AST::ArithmeticOrLogicalExpr::ADD: - op = OPERATOR_PLUS; - break; - case AST::ArithmeticOrLogicalExpr::SUBTRACT: - op = OPERATOR_MINUS; - break; - case AST::ArithmeticOrLogicalExpr::MULTIPLY: - op = OPERATOR_MULT; - break; - case AST::ArithmeticOrLogicalExpr::DIVIDE: - op = OPERATOR_DIV; - break; - case AST::ArithmeticOrLogicalExpr::MODULUS: - op = OPERATOR_MOD; - break; - case AST::ArithmeticOrLogicalExpr::BITWISE_AND: - op = OPERATOR_AND; - break; - case AST::ArithmeticOrLogicalExpr::BITWISE_OR: - op = OPERATOR_OR; - break; - case AST::ArithmeticOrLogicalExpr::BITWISE_XOR: - op = OPERATOR_XOR; - break; - case AST::ArithmeticOrLogicalExpr::LEFT_SHIFT: - op = OPERATOR_LSHIFT; - break; - case AST::ArithmeticOrLogicalExpr::RIGHT_SHIFT: - op = OPERATOR_RSHIFT; - break; - default: - rust_fatal_error (expr.get_locus (), "failed to compile operator"); - return; - } - - auto binExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); - exprs.push_back (binExpr); -} - -void -Compilation::visit (AST::ComparisonExpr &expr) -{ - Bexpression *lhs = NULL; - VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); - if (lhs == NULL) - { - rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Bexpression *rhs = NULL; - VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); - if (rhs == NULL) - { - rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Operator op; - switch (expr.get_expr_type ()) - { - case AST::ComparisonExpr::EQUAL: - op = OPERATOR_EQEQ; - break; - case AST::ComparisonExpr::NOT_EQUAL: - op = OPERATOR_NOTEQ; - break; - case AST::ComparisonExpr::GREATER_THAN: - op = OPERATOR_GT; - break; - case AST::ComparisonExpr::LESS_THAN: - op = OPERATOR_LT; - break; - case AST::ComparisonExpr::GREATER_OR_EQUAL: - op = OPERATOR_GE; - break; - case AST::ComparisonExpr::LESS_OR_EQUAL: - op = OPERATOR_LE; - break; - default: - rust_fatal_error (expr.get_locus (), "failed to compile operator"); - return; - } - - auto compExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); - exprs.push_back (compExpr); -} - -void -Compilation::visit (AST::LazyBooleanExpr &expr) -{ - Bexpression *lhs = NULL; - VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); - if (lhs == NULL) - { - rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Bexpression *rhs = NULL; - VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); - if (rhs == NULL) - { - rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Operator op; - switch (expr.get_expr_type ()) - { - case AST::LazyBooleanExpr::LOGICAL_OR: - op = OPERATOR_OROR; - break; - case AST::LazyBooleanExpr::LOGICAL_AND: - op = OPERATOR_ANDAND; - break; - default: - rust_fatal_error (expr.get_locus (), "failed to compile operator"); - return; - } - - auto compExpr - = backend->binary_expression (op, lhs, rhs, expr.get_locus ()); - exprs.push_back (compExpr); -} - -void -Compilation::visit (AST::TypeCastExpr &expr) -{} - -void -Compilation::visit (AST::AssignmentExpr &expr) -{ - Bexpression *lhs = NULL; - VISIT_POP (expr.get_left_expr ()->get_locus_slow (), expr.get_left_expr ().get (), lhs, exprs); - if (lhs == NULL) - { - rust_error_at (expr.get_left_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - Bexpression *rhs = NULL; - VISIT_POP (expr.get_right_expr ()->get_locus_slow (), expr.get_right_expr ().get (), rhs, exprs); - if (rhs == NULL) - { - rust_error_at (expr.get_right_expr ()->get_locus_slow (), "failed to compile"); - return; - } - - auto s = backend->assignment_statement (scope.GetCurrentFndecl (), lhs, rhs, - expr.get_locus ()); - scope.AddStatement (s); -} - -void -Compilation::visit (AST::CompoundAssignmentExpr &expr) -{} -void -Compilation::visit (AST::GroupedExpr &expr) -{} - -void -Compilation::visit (AST::ArrayElemsValues &elems) -{ - std::vector< ::Bexpression *> elements; - - bool failed = false; - elems.iterate ([&] (AST::Expr *expr) mutable -> bool { - Bexpression *value = nullptr; - VISIT_POP (expr.get_locus_slow (), expr, value, exprs); - if (value == nullptr) - { - rust_fatal_error (expr->get_locus_slow (), - "failed to compile value to array initialiser"); - return false; - } - elements.push_back (value); - return true; - }); - - // nothing to do when its failed - if (failed) - return; - - arrayConsStack.push_back (elements); -} - -void -Compilation::visit (AST::ArrayElemsCopied &elems) -{} - -void -Compilation::visit (AST::ArrayExpr &expr) -{ - translatedType = nullptr; - expr.get_inferred_type ()->accept_vis (*this); - if (translatedType == nullptr) - { - rust_error_at (expr.get_locus_slow (), - "failed to compile array type for ArrayExpr"); - return; - } - - ::Btype *compiledType = translatedType; - translatedType = nullptr; - - auto before = arrayConsStack.size (); - expr.get_array_elems ()->accept_vis (*this); - if (arrayConsStack.size () <= before) - { - rust_error_at (expr.get_locus_slow (), - "failed to compile the array constructor"); - return; - } - std::vector< ::Bexpression *> initializer = arrayConsStack.back (); - arrayConsStack.pop_back (); - - std::vector 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 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 args; - for (auto ¶m : expr.get_params ()) - { - Bexpression *arg = NULL; - VISIT_POP (param->get_locus_slow (), param, arg, exprs); - if (arg == NULL) - { - rust_error_at (param->get_locus_slow (), - "failed to compile argument"); - return; - } - - args.push_back (arg); - } - - auto call = backend->call_expression (scope.GetCurrentFndecl (), fn, args, - NULL, expr.get_locus ()); - exprs.push_back (call); -} - -void -Compilation::visit (AST::MethodCallExpr &expr) -{} -void -Compilation::visit (AST::FieldAccessExpr &expr) -{} -void -Compilation::visit (AST::ClosureExprInner &expr) -{} - -void -Compilation::visit (AST::BlockExpr &expr) -{ - Bblock *enclosingScope = NULL; - Location start_location; /* = stmt.locus; FIXME */ - Location end_location; // FIXME - - std::vector 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 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 (); +// Copyright (C) 2020 Free Software Foundation, Inc. - auto stmt - = backend->if_statement (scope.GetCurrentFndecl (), cond, then_block, - else_block, expr.get_locus ()); - stmts.push_back (stmt); -} +// This file is part of GCC. -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 vars; - auto else_block - = backend->block (scope.GetCurrentFndecl (), scope.CurBlock (), vars, - start_location, end_location); - - scope.PushBlock (else_block); - expr.vis_conseq_if_expr (*this); - // get trailing if required - for (auto &s : stmts) - scope.AddStatement (s); - stmts.clear (); - scope.PopBlock (); - - auto stmt - = backend->if_statement (scope.GetCurrentFndecl (), cond, then_block, - else_block, expr.get_locus ()); - stmts.push_back (stmt); -} - -void -Compilation::visit (AST::IfExprConseqIfLet &expr) -{ - printf ("IfExprConseqIfLet %s\n", expr.as_string ().c_str ()); -} -void -Compilation::visit (AST::IfLetExpr &expr) -{ - printf ("IfLetExpr %s\n", expr.as_string ().c_str ()); -} -void -Compilation::visit (AST::IfLetExprConseqElse &expr) -{ - printf ("IfLetExprConseqElse %s\n", expr.as_string ().c_str ()); -} - -void -Compilation::visit (AST::IfLetExprConseqIf &expr) -{ - printf ("IfLetExprConseqIf %s\n", expr.as_string ().c_str ()); -} - -void -Compilation::visit (AST::IfLetExprConseqIfLet &expr) -{ - printf ("IfLetExprConseqIfLet %s\n", expr.as_string ().c_str ()); -} - -// void Compilation::visit(MatchCase& match_case) {} -/*void -Compilation::visit (AST::MatchCaseBlockExpr &match_case) -{}*/ -/*void -Compilation::visit (AST::MatchCaseExpr &match_case) -{}*/ -void -Compilation::visit (AST::MatchExpr &expr) -{} -void -Compilation::visit (AST::AwaitExpr &expr) -{} -void -Compilation::visit (AST::AsyncBlockExpr &expr) -{} - -// rust-item.h -void -Compilation::visit (AST::TypeParam ¶m) -{} -// void Compilation::visit(WhereClauseItem& item) {} -void -Compilation::visit (AST::LifetimeWhereClauseItem &item) -{} -void -Compilation::visit (AST::TypeBoundWhereClauseItem &item) -{} -void -Compilation::visit (AST::Method &method) -{} -void -Compilation::visit (AST::ModuleBodied &module) -{} -void -Compilation::visit (AST::ModuleNoBody &module) -{} -void -Compilation::visit (AST::ExternCrate &crate) -{} -// void Compilation::visit(UseTree& use_tree) {} -void -Compilation::visit (AST::UseTreeGlob &use_tree) -{} -void -Compilation::visit (AST::UseTreeList &use_tree) -{} -void -Compilation::visit (AST::UseTreeRebind &use_tree) -{} -void -Compilation::visit (AST::UseDeclaration &use_decl) -{} - -void -Compilation::visit (AST::Function &function) -{ - Backend::Btyped_identifier receiver; - std::vector parameters; - std::vector results; - - for (auto ¶m : function.get_function_params ()) - { - // translate the type - translatedType = NULL; - param.get_type ()->accept_vis (*this); - if (translatedType == NULL) - { - rust_error_at (param.get_locus (), "failed to generate type for parameter"); - return; - } - - auto before = patternBuffer.size (); - param.get_pattern ()->accept_vis (*this); - if (patternBuffer.size () <= before) - { - rust_error_at (param.get_locus (), "failed to analyse parameter name"); - return; - } - - auto numParamsPerType = patternBuffer.size () - before; - for (size_t i = 0; i < numParamsPerType; i++) - { - auto paramName = patternBuffer.back (); - patternBuffer.pop_back (); - parameters.push_back ( - Backend::Btyped_identifier (paramName.get_ident (), - translatedType, param.get_locus ())); - } - } - - Btype *returnType = NULL; - if (function.has_return_type ()) - { - translatedType = NULL; - function.get_return_type ()->accept_vis (*this); - if (translatedType == NULL) - { - rust_fatal_error (function.get_locus (), - "failed to generate type for function"); - return; - } - returnType = translatedType; - - // add into the results: - results.push_back ( - Backend::Btyped_identifier ("_", translatedType, Location ())); - } - - 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 ()); - - scope.InsertFunction (function.get_function_name (), fndecl, returnType); - scope.Push (); - - // setup the params - std::vector param_vars; - for (auto ¶m : parameters) - { - bool tree_addressable = false; - auto p = backend->parameter_variable (fndecl, param.name, param.btype, - tree_addressable, param.location); - - scope.InsertVar (param.name, p); - param_vars.push_back (p); - } - - if (!backend->function_set_parameters (fndecl, param_vars)) - { - rust_error_at (function.get_locus (), "failed to setup parameter variables"); - return; - } - - std::vector 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 fields; - for (auto &field : struct_item.get_fields ()) - { - translatedType = NULL; - field.get_field_type ()->accept_vis (*this); - if (translatedType == NULL) - { - rust_fatal_error ( - struct_item.get_locus () /* StructField is mi sing locus */, - "failed to compile struct field"); - return; - } - - fields.push_back (Backend::Btyped_identifier ( - field.get_field_name (), translatedType, - struct_item.get_locus () /* StructField is mi sing locus */)); - } - - auto compiledStruct - = backend->placeholder_struct_type (struct_item.get_struct_name (), - struct_item.get_locus ()); - bool ok = backend->set_placeholder_struct_type (compiledStruct, fields); - if (!ok) - { - rust_fatal_error (struct_item.get_locus (), "failed to compile struct"); - return; - } - - type_decls.push_back (compiledStruct); - scope.InsertType (struct_item.get_struct_name (), compiledStruct); - scope.InsertStructDecl (struct_item.get_struct_name (), &struct_item); -} - -void -Compilation::visit (AST::TupleStruct &tuple_struct) -{} -void -Compilation::visit (AST::EnumItem &item) -{} -void -Compilation::visit (AST::EnumItemTuple &item) -{} -void -Compilation::visit (AST::EnumItemStruct &item) -{} -void -Compilation::visit (AST::EnumItemDiscriminant &item) -{} -void -Compilation::visit (AST::Enum &enum_item) -{} -void -Compilation::visit (AST::Union &union_item) -{} -void -Compilation::visit (AST::ConstantItem &const_item) -{} -void -Compilation::visit (AST::StaticItem &static_item) -{} -void -Compilation::visit (AST::TraitItemFunc &item) -{} -void -Compilation::visit (AST::TraitItemMethod &item) -{} -void -Compilation::visit (AST::TraitItemConst &item) -{} -void -Compilation::visit (AST::TraitItemType &item) -{} -void -Compilation::visit (AST::Trait &trait) -{} -void -Compilation::visit (AST::InherentImpl &impl) -{} -void -Compilation::visit (AST::TraitImpl &impl) -{} -// void Compilation::visit(ExternalItem& item) {} -void -Compilation::visit (AST::ExternalStaticItem &item) -{} -void -Compilation::visit (AST::ExternalFunctionItem &item) -{} -void -Compilation::visit (AST::ExternBlock &block) -{} - -// rust-macro.h -void -Compilation::visit (AST::MacroMatchFragment &match) -{} -void -Compilation::visit (AST::MacroMatchRepetition &match) -{} -void -Compilation::visit (AST::MacroMatcher &matcher) -{} -void -Compilation::visit (AST::MacroRulesDefinition &rules_def) -{} -void -Compilation::visit (AST::MacroInvocation ¯o_invoc) -{} -void -Compilation::visit (AST::MetaItemPath &meta_item) -{} -void -Compilation::visit (AST::MetaItemSeq &meta_item) -{} -void -Compilation::visit (AST::MetaWord &meta_item) -{} -void -Compilation::visit (AST::MetaNameValueStr &meta_item) -{} -void -Compilation::visit (AST::MetaListPaths &meta_item) -{} -void -Compilation::visit (AST::MetaListNameValueStr &meta_item) -{} - -// rust-pattern.h -void -Compilation::visit (AST::LiteralPattern &pattern) -{ - printf ("LiteralPattern: %s\n", pattern.as_string ().c_str ()); -} - -void -Compilation::visit (AST::IdentifierPattern &pattern) -{ - patternBuffer.push_back (pattern); -} - -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) -{} - -// rust-stmt.h -void -Compilation::visit (AST::EmptyStmt &stmt) -{} -void - -Compilation::visit (AST::LetStmt &stmt) -{ - if (!stmt.has_init_expr ()) - return; +// 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. - 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; - } +// 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. - 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 (); -} - -void -Compilation::visit (AST::ExprStmtWithoutBlock &stmt) -{ - stmt.get_expr ()->accept_vis (*this); -} - -void -Compilation::visit (AST::ExprStmtWithBlock &stmt) -{ - Bblock *enclosingScope = NULL; - Location start_location; /* = stmt.locus; FIXME */ - Location end_location; // FIXME - - std::vector 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); -} - -// 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) -{} +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . -void -Compilation::visit (AST::ArrayType &type) -{ - 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; +#include "rust-compile.h" +#include "rust-diagnostics.h" - 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; - } +namespace Rust { +namespace Compile { - translatedType = backend->array_type (elementType, length); -} +CompileCrate::~CompileCrate () {} void -Compilation::visit (AST::SliceType &type) -{} -void -Compilation::visit (AST::InferredType &type) -{} -void -Compilation::visit (AST::BareFunctionType &type) +CompileCrate::Compile (HIR::Crate &crate, Context *ctx) {} } // namespace Compile diff --git a/gcc/rust/backend/rust-compile.h b/gcc/rust/backend/rust-compile.h index 88c8318..5ee1122 100644 --- a/gcc/rust/backend/rust-compile.h +++ b/gcc/rust/backend/rust-compile.h @@ -1,257 +1,89 @@ -#pragma once +// 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 +// . + +#ifndef RUST_COMPILE_H +#define RUST_COMPILE_H #include "rust-system.h" -#include "rust-ast-full.h" -#include "rust-ast-visitor.h" +#include "rust-hir-map.h" +#include "rust-name-resolver.h" +#include "rust-hir-type-check.h" +#include "rust-linemap.h" #include "rust-backend.h" -#include "cscope.h" namespace Rust { namespace Compile { -class Compilation : public AST::ASTVisitor +class Context { public: - static bool Compile (AST::Crate &crate, ::Backend *backend); - - ~Compilation (); - - // visitor impl - // rust-ast.h - // virtual void visit(AttrInput& attr_input); - // virtual void visit(TokenTree& token_tree); - // virtual void visit(MacroMatch& macro_match); - virtual void visit (AST::Token &tok); - virtual void visit (AST::DelimTokenTree &delim_tok_tree); - virtual void visit (AST::AttrInputMetaItemContainer &input); - // virtual void visit(MetaItem& meta_item); - // virtual void vsit(Stmt& stmt); - // virtual void visit(Expr& expr); - virtual void visit (AST::IdentifierExpr &ident_expr); - // virtual void visit(Pattern& pattern); - // virtual void visit(Type& type); - // virtual void visit(TypeParamBound& type_param_bound); - virtual void visit (AST::Lifetime &lifetime); - // virtual void visit(GenericParam& generic_param); - virtual void visit (AST::LifetimeParam &lifetime_param); - // virtual void visit(TraitItem& trait_item); - // virtual void visit(InherentImplItem& inherent_impl_item); - // virtual void visit(TraitImplItem& trait_impl_item); - virtual void visit (AST::MacroInvocationSemi ¯o); - - // rust-path.h - virtual void visit (AST::PathInExpression &path); - virtual void visit (AST::TypePathSegment &segment); - virtual void visit (AST::TypePathSegmentGeneric &segment); - virtual void visit (AST::TypePathSegmentFunction &segment); - virtual void visit (AST::TypePath &path); - virtual void visit (AST::QualifiedPathInExpression &path); - virtual void visit (AST::QualifiedPathInType &path); - - // rust-expr.h - virtual void visit (AST::LiteralExpr &expr); - virtual void visit (AST::AttrInputLiteral &attr_input); - virtual void visit (AST::MetaItemLitExpr &meta_item); - virtual void visit (AST::MetaItemPathLit &meta_item); - virtual void visit (AST::BorrowExpr &expr); - virtual void visit (AST::DereferenceExpr &expr); - virtual void visit (AST::ErrorPropagationExpr &expr); - virtual void visit (AST::NegationExpr &expr); - virtual void visit (AST::ArithmeticOrLogicalExpr &expr); - virtual void visit (AST::ComparisonExpr &expr); - virtual void visit (AST::LazyBooleanExpr &expr); - virtual void visit (AST::TypeCastExpr &expr); - virtual void visit (AST::AssignmentExpr &expr); - virtual void visit (AST::CompoundAssignmentExpr &expr); - virtual void visit (AST::GroupedExpr &expr); - // virtual void visit(ArrayElems& elems); - virtual void visit (AST::ArrayElemsValues &elems); - virtual void visit (AST::ArrayElemsCopied &elems); - virtual void visit (AST::ArrayExpr &expr); - virtual void visit (AST::ArrayIndexExpr &expr); - virtual void visit (AST::TupleExpr &expr); - virtual void visit (AST::TupleIndexExpr &expr); - virtual void visit (AST::StructExprStruct &expr); - // virtual void visit(StructExprField& field); - virtual void visit (AST::StructExprFieldIdentifier &field); - virtual void visit (AST::StructExprFieldIdentifierValue &field); - virtual void visit (AST::StructExprFieldIndexValue &field); - virtual void visit (AST::StructExprStructFields &expr); - virtual void visit (AST::StructExprStructBase &expr); - virtual void visit (AST::StructExprTuple &expr); - virtual void visit (AST::StructExprUnit &expr); - // virtual void visit(EnumExprField& field); - virtual void visit (AST::EnumExprFieldIdentifier &field); - virtual void visit (AST::EnumExprFieldIdentifierValue &field); - virtual void visit (AST::EnumExprFieldIndexValue &field); - virtual void visit (AST::EnumExprStruct &expr); - virtual void visit (AST::EnumExprTuple &expr); - virtual void visit (AST::EnumExprFieldless &expr); - virtual void visit (AST::CallExpr &expr); - virtual void visit (AST::MethodCallExpr &expr); - virtual void visit (AST::FieldAccessExpr &expr); - virtual void visit (AST::ClosureExprInner &expr); - virtual void visit (AST::BlockExpr &expr); - virtual void visit (AST::ClosureExprInnerTyped &expr); - virtual void visit (AST::ContinueExpr &expr); - virtual void visit (AST::BreakExpr &expr); - virtual void visit (AST::RangeFromToExpr &expr); - virtual void visit (AST::RangeFromExpr &expr); - virtual void visit (AST::RangeToExpr &expr); - virtual void visit (AST::RangeFullExpr &expr); - virtual void visit (AST::RangeFromToInclExpr &expr); - virtual void visit (AST::RangeToInclExpr &expr); - virtual void visit (AST::ReturnExpr &expr); - virtual void visit (AST::UnsafeBlockExpr &expr); - virtual void visit (AST::LoopExpr &expr); - virtual void visit (AST::WhileLoopExpr &expr); - virtual void visit (AST::WhileLetLoopExpr &expr); - virtual void visit (AST::ForLoopExpr &expr); - virtual void visit (AST::IfExpr &expr); - virtual void visit (AST::IfExprConseqElse &expr); - virtual void visit (AST::IfExprConseqIf &expr); - virtual void visit (AST::IfExprConseqIfLet &expr); - virtual void visit (AST::IfLetExpr &expr); - virtual void visit (AST::IfLetExprConseqElse &expr); - virtual void visit (AST::IfLetExprConseqIf &expr); - virtual void visit (AST::IfLetExprConseqIfLet &expr); - // virtual void visit(MatchCase& match_case); - // virtual void visit (AST::MatchCaseBlockExpr &match_case); - // virtual void visit (AST::MatchCaseExpr &match_case); - virtual void visit (AST::MatchExpr &expr); - virtual void visit (AST::AwaitExpr &expr); - virtual void visit (AST::AsyncBlockExpr &expr); - - // rust-item.h - virtual void visit (AST::TypeParam ¶m); - // virtual void visit(WhereClauseItem& item); - virtual void visit (AST::LifetimeWhereClauseItem &item); - virtual void visit (AST::TypeBoundWhereClauseItem &item); - virtual void visit (AST::Method &method); - virtual void visit (AST::ModuleBodied &module); - virtual void visit (AST::ModuleNoBody &module); - virtual void visit (AST::ExternCrate &crate); - // virtual void visit(UseTree& use_tree); - virtual void visit (AST::UseTreeGlob &use_tree); - virtual void visit (AST::UseTreeList &use_tree); - virtual void visit (AST::UseTreeRebind &use_tree); - virtual void visit (AST::UseDeclaration &use_decl); - virtual void visit (AST::Function &function); - virtual void visit (AST::TypeAlias &type_alias); - virtual void visit (AST::StructStruct &struct_item); - virtual void visit (AST::TupleStruct &tuple_struct); - virtual void visit (AST::EnumItem &item); - virtual void visit (AST::EnumItemTuple &item); - virtual void visit (AST::EnumItemStruct &item); - virtual void visit (AST::EnumItemDiscriminant &item); - virtual void visit (AST::Enum &enum_item); - virtual void visit (AST::Union &union_item); - virtual void visit (AST::ConstantItem &const_item); - virtual void visit (AST::StaticItem &static_item); - virtual void visit (AST::TraitItemFunc &item); - virtual void visit (AST::TraitItemMethod &item); - virtual void visit (AST::TraitItemConst &item); - virtual void visit (AST::TraitItemType &item); - virtual void visit (AST::Trait &trait); - virtual void visit (AST::InherentImpl &impl); - virtual void visit (AST::TraitImpl &impl); - // virtual void visit(ExternalItem& item); - virtual void visit (AST::ExternalStaticItem &item); - virtual void visit (AST::ExternalFunctionItem &item); - virtual void visit (AST::ExternBlock &block); - - // rust-macro.h - virtual void visit (AST::MacroMatchFragment &match); - virtual void visit (AST::MacroMatchRepetition &match); - virtual void visit (AST::MacroMatcher &matcher); - virtual void visit (AST::MacroRulesDefinition &rules_def); - virtual void visit (AST::MacroInvocation ¯o_invoc); - virtual void visit (AST::MetaItemPath &meta_item); - virtual void visit (AST::MetaItemSeq &meta_item); - virtual void visit (AST::MetaWord &meta_item); - virtual void visit (AST::MetaNameValueStr &meta_item); - virtual void visit (AST::MetaListPaths &meta_item); - virtual void visit (AST::MetaListNameValueStr &meta_item); - - // rust-pattern.h - virtual void visit (AST::LiteralPattern &pattern); - virtual void visit (AST::IdentifierPattern &pattern); - virtual void visit (AST::WildcardPattern &pattern); - // virtual void visit(RangePatternBound& bound); - virtual void visit (AST::RangePatternBoundLiteral &bound); - virtual void visit (AST::RangePatternBoundPath &bound); - virtual void visit (AST::RangePatternBoundQualPath &bound); - virtual void visit (AST::RangePattern &pattern); - virtual void visit (AST::ReferencePattern &pattern); - // virtual void visit(StructPatternField& field); - virtual void visit (AST::StructPatternFieldTuplePat &field); - virtual void visit (AST::StructPatternFieldIdentPat &field); - virtual void visit (AST::StructPatternFieldIdent &field); - virtual void visit (AST::StructPattern &pattern); - // virtual void visit(TupleStructItems& tuple_items); - virtual void visit (AST::TupleStructItemsNoRange &tuple_items); - virtual void visit (AST::TupleStructItemsRange &tuple_items); - virtual void visit (AST::TupleStructPattern &pattern); - // virtual void visit(TuplePatternItems& tuple_items); - virtual void visit (AST::TuplePatternItemsMultiple &tuple_items); - virtual void visit (AST::TuplePatternItemsRanged &tuple_items); - virtual void visit (AST::TuplePattern &pattern); - virtual void visit (AST::GroupedPattern &pattern); - virtual void visit (AST::SlicePattern &pattern); - - // rust-stmt.h - virtual void visit (AST::EmptyStmt &stmt); - virtual void visit (AST::LetStmt &stmt); - virtual void visit (AST::ExprStmtWithoutBlock &stmt); - virtual void visit (AST::ExprStmtWithBlock &stmt); - - // rust-type.h - virtual void visit (AST::TraitBound &bound); - virtual void visit (AST::ImplTraitType &type); - virtual void visit (AST::TraitObjectType &type); - virtual void visit (AST::ParenthesisedType &type); - virtual void visit (AST::ImplTraitTypeOneBound &type); - virtual void visit (AST::TraitObjectTypeOneBound &type); - virtual void visit (AST::TupleType &type); - virtual void visit (AST::NeverType &type); - virtual void visit (AST::RawPointerType &type); - virtual void visit (AST::ReferenceType &type); - virtual void visit (AST::ArrayType &type); - virtual void visit (AST::SliceType &type); - virtual void visit (AST::InferredType &type); - virtual void visit (AST::BareFunctionType &type); + Context (::Backend *backend) + : backend (backend), resolver (Resolver::Resolver::get ()), + tyctx (Resolver::TypeCheckContext::get ()), + mappings (Analysis::Mappings::get ()) + {} + + ~Context () {} + + ::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_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); + } private: - Compilation (AST::Crate &crate, Backend *backend); - bool go (); + ::Backend *backend; + Resolver::Resolver *resolver; + Resolver::TypeCheckContext *tyctx; + Analysis::Mappings *mappings; - AST::Crate &crate; - Backend *backend; - - // utils - bool compileVarDecl (Bfunction *fndecl, AST::LetStmt *stmt, - std::vector &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 patternBuffer; - std::vector< ::Bexpression *> exprs; - std::vector< ::Bstatement *> stmts; - std::vector< ::Bvariable *> varBuffer; - std::vector structBuffer; - std::vector > arrayConsStack; - - // careful these are the vectors we pass into the GCC middle-end + // 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 CompileCrate +{ +public: + static void Compile (HIR::Crate &crate, Context *ctx); + + ~CompileCrate (); + +private: + CompileCrate (HIR::Crate &crate, Context *ctx); + + HIR::Crate &crate; + Context *ctx; +}; + } // namespace Compile } // namespace Rust + +#endif // RUST_COMPILE_H diff --git a/gcc/rust/rust-session-manager.cc b/gcc/rust/rust-session-manager.cc index fc64994..17ff24a 100644 --- a/gcc/rust/rust-session-manager.cc +++ b/gcc/rust/rust-session-manager.cc @@ -30,11 +30,11 @@ #include "rust-lex.h" #include "rust-parse.h" -#include "rust-scan.h" #include "rust-macro-expand.h" #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 (); @@ -529,6 +529,9 @@ Session::parse_file (const char *filename) // TODO: what do I dump here? resolved names? AST with resolved names? } + if (saw_errors ()) + return; + // lower AST to HIR HIR::Crate hir = lower_ast (parsed_crate); if (options.dump_option == CompileOptions::HIR_DUMP) @@ -537,6 +540,9 @@ Session::parse_file (const char *filename) return; } + if (saw_errors ()) + return; + // type resolve type_resolution (hir); @@ -544,7 +550,14 @@ Session::parse_file (const char *filename) 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 diff --git a/gcc/rust/util/scope.h b/gcc/rust/util/scope.h deleted file mode 100644 index 6e853c3..0000000 --- a/gcc/rust/util/scope.h +++ /dev/null @@ -1,78 +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 -// . - -#ifndef RUST_SCOPE_H -#define RUST_SCOPE_H - -#include "rust-system.h" -#include "rust-ast-full.h" - -namespace Rust { -namespace Analysis { - -template 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 Pop () - { - auto toplevel = scopeStack.back (); - scopeStack.pop_back (); - return toplevel; - } - - std ::map Peek () { return scopeStack.back (); } - -private: - std::vector > scopeStack; -}; - -} // namespace Analysis -} // namespace Rust - -#endif // RUST_SCOPE_H -- cgit v1.1 From 6136f0aebbb84cbcf8f92bed206733391aaa3866 Mon Sep 17 00:00:00 2001 From: Philip Herron Date: Tue, 15 Dec 2020 17:48:11 +0000 Subject: This is a new HIR -> GIMPLE pass it reuses the mappings from hir, name resolution and type resolution to simplify the generation of gimple. --- gcc/rust/Make-lang.in | 1 + gcc/rust/backend/rust-compile-base.h | 249 +++++++++++++++++++ gcc/rust/backend/rust-compile-context.h | 247 +++++++++++++++++++ gcc/rust/backend/rust-compile-expr.h | 285 ++++++++++++++++++++++ gcc/rust/backend/rust-compile-item.h | 180 ++++++++++++++ gcc/rust/backend/rust-compile-resolve-path.cc | 81 ++++++ gcc/rust/backend/rust-compile-resolve-path.h | 52 ++++ gcc/rust/backend/rust-compile-stmt.h | 85 +++++++ gcc/rust/backend/rust-compile-tyty.h | 247 +++++++++++++++++++ gcc/rust/backend/rust-compile-var-decl.h | 69 ++++++ gcc/rust/backend/rust-compile.cc | 19 +- gcc/rust/backend/rust-compile.h | 48 +--- gcc/rust/hir/rust-ast-lower-item.h | 29 ++- gcc/rust/hir/rust-ast-lower-stmt.h | 2 + gcc/rust/hir/tree/rust-hir-expr.h | 11 + gcc/rust/hir/tree/rust-hir-item.h | 23 +- gcc/rust/hir/tree/rust-hir-stmt.h | 4 + gcc/rust/resolve/rust-ast-resolve-expr.h | 10 +- gcc/rust/resolve/rust-ast-resolve-pattern.h | 1 - gcc/rust/resolve/rust-ast-resolve-stmt.h | 5 + gcc/rust/typecheck/rust-hir-type-check-expr.h | 29 ++- gcc/rust/typecheck/rust-hir-type-check-item.h | 1 + gcc/rust/typecheck/rust-hir-type-check-stmt.h | 5 + gcc/rust/typecheck/rust-hir-type-check-toplevel.h | 13 +- gcc/rust/typecheck/rust-hir-type-check-type.h | 3 +- gcc/rust/typecheck/rust-hir-type-check.h | 1 + gcc/rust/typecheck/rust-tyctx.cc | 16 +- gcc/rust/typecheck/rust-tyty-rules.h | 4 +- gcc/rust/typecheck/rust-tyty.cc | 2 +- gcc/rust/typecheck/rust-tyty.h | 35 +-- gcc/rust/util/rust-hir-map.cc | 66 +++++ gcc/rust/util/rust-hir-map.h | 14 ++ 32 files changed, 1738 insertions(+), 99 deletions(-) create mode 100644 gcc/rust/backend/rust-compile-base.h create mode 100644 gcc/rust/backend/rust-compile-context.h create mode 100644 gcc/rust/backend/rust-compile-expr.h create mode 100644 gcc/rust/backend/rust-compile-item.h create mode 100644 gcc/rust/backend/rust-compile-resolve-path.cc create mode 100644 gcc/rust/backend/rust-compile-resolve-path.h create mode 100644 gcc/rust/backend/rust-compile-stmt.h create mode 100644 gcc/rust/backend/rust-compile-tyty.h create mode 100644 gcc/rust/backend/rust-compile-var-decl.h (limited to 'gcc') diff --git a/gcc/rust/Make-lang.in b/gcc/rust/Make-lang.in index 56f308e..5ac60ea 100644 --- a/gcc/rust/Make-lang.in +++ b/gcc/rust/Make-lang.in @@ -70,6 +70,7 @@ GRS_OBJS = \ rust/rust-ast-full-test.o \ rust/rust-session-manager.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 \ 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 +// . + +#ifndef RUST_COMPILE_BASE +#define RUST_COMPILE_BASE + +#include "rust-compile-context.h" +#include "rust-hir-visitor.h" +#include "rust-hir-full.h" + +namespace Rust { +namespace Compile { + +class HIRCompileBase : public HIR::HIRVisitor +{ +public: + virtual ~HIRCompileBase () {} + + // rust-ast.h + // virtual void visit(AttrInput& attr_input) {} + // virtual void visit(TokenTree& token_tree) {} + // virtual void visit(MacroMatch& macro_match) {} + virtual void visit (HIR::Token &tok) {} + virtual void visit (HIR::DelimTokenTree &delim_tok_tree) {} + virtual void visit (HIR::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // virtual void visit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (HIR::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (HIR::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (HIR::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (HIR::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (HIR::PathInExpression &path) {} + virtual void visit (HIR::TypePathSegment &segment) {} + virtual void visit (HIR::TypePathSegmentGeneric &segment) {} + virtual void visit (HIR::TypePathSegmentFunction &segment) {} + virtual void visit (HIR::TypePath &path) {} + virtual void visit (HIR::QualifiedPathInExpression &path) {} + virtual void visit (HIR::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (HIR::LiteralExpr &expr) {} + virtual void visit (HIR::AttrInputLiteral &attr_input) {} + virtual void visit (HIR::MetaItemLitExpr &meta_item) {} + virtual void visit (HIR::MetaItemPathLit &meta_item) {} + virtual void visit (HIR::BorrowExpr &expr) {} + virtual void visit (HIR::DereferenceExpr &expr) {} + virtual void visit (HIR::ErrorPropagationExpr &expr) {} + virtual void visit (HIR::NegationExpr &expr) {} + virtual void visit (HIR::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (HIR::ComparisonExpr &expr) {} + virtual void visit (HIR::LazyBooleanExpr &expr) {} + virtual void visit (HIR::TypeCastExpr &expr) {} + virtual void visit (HIR::AssignmentExpr &expr) {} + virtual void visit (HIR::CompoundAssignmentExpr &expr) {} + virtual void visit (HIR::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (HIR::ArrayElemsValues &elems) {} + virtual void visit (HIR::ArrayElemsCopied &elems) {} + virtual void visit (HIR::ArrayExpr &expr) {} + virtual void visit (HIR::ArrayIndexExpr &expr) {} + virtual void visit (HIR::TupleExpr &expr) {} + virtual void visit (HIR::TupleIndexExpr &expr) {} + virtual void visit (HIR::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (HIR::StructExprFieldIdentifier &field) {} + virtual void visit (HIR::StructExprFieldIdentifierValue &field) {} + virtual void visit (HIR::StructExprFieldIndexValue &field) {} + virtual void visit (HIR::StructExprStructFields &expr) {} + virtual void visit (HIR::StructExprStructBase &expr) {} + virtual void visit (HIR::StructExprTuple &expr) {} + virtual void visit (HIR::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (HIR::EnumExprFieldIdentifier &field) {} + virtual void visit (HIR::EnumExprFieldIdentifierValue &field) {} + virtual void visit (HIR::EnumExprFieldIndexValue &field) {} + virtual void visit (HIR::EnumExprStruct &expr) {} + virtual void visit (HIR::EnumExprTuple &expr) {} + virtual void visit (HIR::EnumExprFieldless &expr) {} + virtual void visit (HIR::CallExpr &expr) {} + virtual void visit (HIR::MethodCallExpr &expr) {} + virtual void visit (HIR::FieldAccessExpr &expr) {} + virtual void visit (HIR::ClosureExprInner &expr) {} + virtual void visit (HIR::BlockExpr &expr) {} + virtual void visit (HIR::ClosureExprInnerTyped &expr) {} + virtual void visit (HIR::ContinueExpr &expr) {} + virtual void visit (HIR::BreakExpr &expr) {} + virtual void visit (HIR::RangeFromToExpr &expr) {} + virtual void visit (HIR::RangeFromExpr &expr) {} + virtual void visit (HIR::RangeToExpr &expr) {} + virtual void visit (HIR::RangeFullExpr &expr) {} + virtual void visit (HIR::RangeFromToInclExpr &expr) {} + virtual void visit (HIR::RangeToInclExpr &expr) {} + virtual void visit (HIR::ReturnExpr &expr) {} + virtual void visit (HIR::UnsafeBlockExpr &expr) {} + virtual void visit (HIR::LoopExpr &expr) {} + virtual void visit (HIR::WhileLoopExpr &expr) {} + virtual void visit (HIR::WhileLetLoopExpr &expr) {} + virtual void visit (HIR::ForLoopExpr &expr) {} + virtual void visit (HIR::IfExpr &expr) {} + virtual void visit (HIR::IfExprConseqElse &expr) {} + virtual void visit (HIR::IfExprConseqIf &expr) {} + virtual void visit (HIR::IfExprConseqIfLet &expr) {} + virtual void visit (HIR::IfLetExpr &expr) {} + virtual void visit (HIR::IfLetExprConseqElse &expr) {} + virtual void visit (HIR::IfLetExprConseqIf &expr) {} + virtual void visit (HIR::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (HIR::MatchCaseBlockExpr &match_case) {} + // virtual void visit (HIR::MatchCaseExpr &match_case) {} + virtual void visit (HIR::MatchExpr &expr) {} + virtual void visit (HIR::AwaitExpr &expr) {} + virtual void visit (HIR::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (HIR::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (HIR::LifetimeWhereClauseItem &item) {} + virtual void visit (HIR::TypeBoundWhereClauseItem &item) {} + virtual void visit (HIR::Method &method) {} + virtual void visit (HIR::ModuleBodied &module) {} + virtual void visit (HIR::ModuleNoBody &module) {} + virtual void visit (HIR::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (HIR::UseTreeGlob &use_tree) {} + virtual void visit (HIR::UseTreeList &use_tree) {} + virtual void visit (HIR::UseTreeRebind &use_tree) {} + virtual void visit (HIR::UseDeclaration &use_decl) {} + virtual void visit (HIR::Function &function) {} + virtual void visit (HIR::TypeAlias &type_alias) {} + virtual void visit (HIR::StructStruct &struct_item) {} + virtual void visit (HIR::TupleStruct &tuple_struct) {} + virtual void visit (HIR::EnumItem &item) {} + virtual void visit (HIR::EnumItemTuple &item) {} + virtual void visit (HIR::EnumItemStruct &item) {} + virtual void visit (HIR::EnumItemDiscriminant &item) {} + virtual void visit (HIR::Enum &enum_item) {} + virtual void visit (HIR::Union &union_item) {} + virtual void visit (HIR::ConstantItem &const_item) {} + virtual void visit (HIR::StaticItem &static_item) {} + virtual void visit (HIR::TraitItemFunc &item) {} + virtual void visit (HIR::TraitItemMethod &item) {} + virtual void visit (HIR::TraitItemConst &item) {} + virtual void visit (HIR::TraitItemType &item) {} + virtual void visit (HIR::Trait &trait) {} + virtual void visit (HIR::InherentImpl &impl) {} + virtual void visit (HIR::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (HIR::ExternalStaticItem &item) {} + virtual void visit (HIR::ExternalFunctionItem &item) {} + virtual void visit (HIR::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (HIR::MacroMatchFragment &match) {} + virtual void visit (HIR::MacroMatchRepetition &match) {} + virtual void visit (HIR::MacroMatcher &matcher) {} + virtual void visit (HIR::MacroRulesDefinition &rules_def) {} + virtual void visit (HIR::MacroInvocation ¯o_invoc) {} + virtual void visit (HIR::MetaItemPath &meta_item) {} + virtual void visit (HIR::MetaItemSeq &meta_item) {} + virtual void visit (HIR::MetaWord &meta_item) {} + virtual void visit (HIR::MetaNameValueStr &meta_item) {} + virtual void visit (HIR::MetaListPaths &meta_item) {} + virtual void visit (HIR::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (HIR::LiteralPattern &pattern) {} + virtual void visit (HIR::IdentifierPattern &pattern) {} + virtual void visit (HIR::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (HIR::RangePatternBoundLiteral &bound) {} + virtual void visit (HIR::RangePatternBoundPath &bound) {} + virtual void visit (HIR::RangePatternBoundQualPath &bound) {} + virtual void visit (HIR::RangePattern &pattern) {} + virtual void visit (HIR::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (HIR::StructPatternFieldTuplePat &field) {} + virtual void visit (HIR::StructPatternFieldIdentPat &field) {} + virtual void visit (HIR::StructPatternFieldIdent &field) {} + virtual void visit (HIR::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (HIR::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (HIR::TupleStructItemsRange &tuple_items) {} + virtual void visit (HIR::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (HIR::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (HIR::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (HIR::TuplePattern &pattern) {} + virtual void visit (HIR::GroupedPattern &pattern) {} + virtual void visit (HIR::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (HIR::EmptyStmt &stmt) {} + virtual void visit (HIR::LetStmt &stmt) {} + virtual void visit (HIR::ExprStmtWithoutBlock &stmt) {} + virtual void visit (HIR::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (HIR::TraitBound &bound) {} + virtual void visit (HIR::ImplTraitType &type) {} + virtual void visit (HIR::TraitObjectType &type) {} + virtual void visit (HIR::ParenthesisedType &type) {} + virtual void visit (HIR::ImplTraitTypeOneBound &type) {} + virtual void visit (HIR::TraitObjectTypeOneBound &type) {} + virtual void visit (HIR::TupleType &type) {} + virtual void visit (HIR::NeverType &type) {} + virtual void visit (HIR::RawPointerType &type) {} + virtual void visit (HIR::ReferenceType &type) {} + virtual void visit (HIR::ArrayType &type) {} + virtual void visit (HIR::SliceType &type) {} + virtual void visit (HIR::InferredType &type) {} + virtual void visit (HIR::BareFunctionType &type) {} + +protected: + HIRCompileBase (Context *ctx) : ctx (ctx) {} + + Context *get_context () { return ctx; } + + Context *ctx; +}; + +} // namespace Compile +} // namespace Rust + +#endif // RUST_COMPILE_BASE diff --git a/gcc/rust/backend/rust-compile-context.h b/gcc/rust/backend/rust-compile-context.h new file mode 100644 index 0000000..f890678 --- /dev/null +++ b/gcc/rust/backend/rust-compile-context.h @@ -0,0 +1,247 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// . + +#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 fn_stack; + std::map compiled_var_decls; + std::map compiled_type_map; + std::map compiled_fn_map; + std::vector< ::std::vector > 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 +// . + +#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 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 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 +// . + +#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 typarams + = TyTyExtractParamsFromFnType::compile (fnType); + std::vector 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 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 +// . + +#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 +// . + +#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 +// . + +#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 +// . + +#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 parameters; + std::vector 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 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 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 +// . + +#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 a4b5cd4..11c380b 100644 --- a/gcc/rust/backend/rust-compile.cc +++ b/gcc/rust/backend/rust-compile.cc @@ -17,16 +17,31 @@ // . #include "rust-compile.h" -#include "rust-diagnostics.h" +#include "rust-compile-item.h" namespace Rust { namespace Compile { +CompileCrate::CompileCrate (HIR::Crate &crate, Context *ctx) + : crate (crate), ctx (ctx) +{} + CompileCrate::~CompileCrate () {} void CompileCrate::Compile (HIR::Crate &crate, Context *ctx) -{} + +{ + CompileCrate c (crate, ctx); + c.go (); +} + +void +CompileCrate::go () +{ + for (auto it = crate.items.begin (); it != crate.items.end (); it++) + CompileItem::compile (it->get (), ctx); +} } // namespace Compile } // namespace Rust diff --git a/gcc/rust/backend/rust-compile.h b/gcc/rust/backend/rust-compile.h index 5ee1122..18f3e54 100644 --- a/gcc/rust/backend/rust-compile.h +++ b/gcc/rust/backend/rust-compile.h @@ -20,55 +20,12 @@ #define RUST_COMPILE_H #include "rust-system.h" -#include "rust-hir-map.h" -#include "rust-name-resolver.h" -#include "rust-hir-type-check.h" -#include "rust-linemap.h" -#include "rust-backend.h" +#include "rust-hir-full.h" +#include "rust-compile-context.h" namespace Rust { namespace Compile { -class Context -{ -public: - Context (::Backend *backend) - : backend (backend), resolver (Resolver::Resolver::get ()), - tyctx (Resolver::TypeCheckContext::get ()), - mappings (Analysis::Mappings::get ()) - {} - - ~Context () {} - - ::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_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); - } - -private: - ::Backend *backend; - Resolver::Resolver *resolver; - Resolver::TypeCheckContext *tyctx; - Analysis::Mappings *mappings; - - // 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 CompileCrate { public: @@ -78,6 +35,7 @@ public: private: CompileCrate (HIR::Crate &crate, Context *ctx); + void go (); HIR::Crate &crate; Context *ctx; diff --git a/gcc/rust/hir/rust-ast-lower-item.h b/gcc/rust/hir/rust-ast-lower-item.h index e0ce862..e6c86b8 100644 --- a/gcc/rust/hir/rust-ast-lower-item.h +++ b/gcc/rust/hir/rust-ast-lower-item.h @@ -69,9 +69,16 @@ public: auto translated_type = std::unique_ptr ( ASTLoweringType::translate (param.get_type ().get ())); - function_params.push_back ( - HIR::FunctionParam (std::move (translated_pattern), - std::move (translated_type), param.get_locus ())); + 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 function_body @@ -83,7 +90,7 @@ public: mappings->get_next_hir_id (crate_num), mappings->get_next_localdef_id (crate_num)); - translated + 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), @@ -92,9 +99,21 @@ public: mappings->insert_defid_mapping (mapping.get_defid (), translated); mappings->insert_hir_item (mapping.get_crate_num (), mapping.get_hirid (), - translated); + fn); mappings->insert_location (crate_num, mapping.get_hirid (), function.get_locus ()); + + // add the mappings for the function params at the end + for (auto ¶m : fn->function_params) + { + mappings->insert_hir_param (mapping.get_crate_num (), + param.get_mappings ()->get_hirid (), + ¶m); + mappings->insert_location (crate_num, mapping.get_hirid (), + param.get_locus ()); + } + + translated = fn; } // Helpers diff --git a/gcc/rust/hir/rust-ast-lower-stmt.h b/gcc/rust/hir/rust-ast-lower-stmt.h index c813639..c57d14f 100644 --- a/gcc/rust/hir/rust-ast-lower-stmt.h +++ b/gcc/rust/hir/rust-ast-lower-stmt.h @@ -60,6 +60,7 @@ public: 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) @@ -86,6 +87,7 @@ public: 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: diff --git a/gcc/rust/hir/tree/rust-hir-expr.h b/gcc/rust/hir/tree/rust-hir-expr.h index b08aa91..36c2085 100644 --- a/gcc/rust/hir/tree/rust-hir-expr.h +++ b/gcc/rust/hir/tree/rust-hir-expr.h @@ -536,6 +536,7 @@ public: 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? */ @@ -610,6 +611,8 @@ public: 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 */ @@ -2562,6 +2565,14 @@ public: } } + 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 */ diff --git a/gcc/rust/hir/tree/rust-hir-item.h b/gcc/rust/hir/tree/rust-hir-item.h index cf24bae..e0477f4 100644 --- a/gcc/rust/hir/tree/rust-hir-item.h +++ b/gcc/rust/hir/tree/rust-hir-item.h @@ -409,17 +409,20 @@ public: std::unique_ptr type; Location locus; + Analysis::NodeMapping mappings; - FunctionParam (std::unique_ptr param_name, + FunctionParam (Analysis::NodeMapping mappings, + std::unique_ptr param_name, std::unique_ptr param_type, Location locus) : param_name (std::move (param_name)), type (std::move (param_type)), - locus (locus) + 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) + type (other.type->clone_type ()), locus (other.locus), + mappings (other.mappings) {} // Overload assignment operator to use clone @@ -428,6 +431,7 @@ public: param_name = other.param_name->clone_pattern (); type = other.type->clone_type (); locus = other.locus; + mappings = other.mappings; return *this; } @@ -436,15 +440,6 @@ public: FunctionParam (FunctionParam &&other) = default; FunctionParam &operator= (FunctionParam &&other) = default; - // Returns whether FunctionParam is in an invalid state. - bool is_error () const { return param_name == nullptr || type == nullptr; } - - // Creates an error FunctionParam. - static FunctionParam create_error () - { - return FunctionParam (nullptr, nullptr, Location ()); - } - std::string as_string () const; Location get_locus () const { return locus; } @@ -452,6 +447,8 @@ public: 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 @@ -1191,8 +1188,6 @@ public: Location locus; - std::vector locals; - std::string as_string () const override; // Returns whether function has generic parameters. diff --git a/gcc/rust/hir/tree/rust-hir-stmt.h b/gcc/rust/hir/tree/rust-hir-stmt.h index 31d55b6..c799b5e 100644 --- a/gcc/rust/hir/tree/rust-hir-stmt.h +++ b/gcc/rust/hir/tree/rust-hir-stmt.h @@ -117,6 +117,8 @@ public: 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 */ @@ -174,6 +176,8 @@ public: 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 */ diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h index b9e7f6a..9e98fda 100644 --- a/gcc/rust/resolve/rust-ast-resolve-expr.h +++ b/gcc/rust/resolve/rust-ast-resolve-expr.h @@ -38,7 +38,13 @@ public: void visit (AST::PathInExpression &expr) { - if (resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + 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 (), @@ -60,7 +66,7 @@ public: ResolveExpr::go (p, expr.get_node_id ()); return true; }); - /// resolver->insert_resolved_name(NodeId refId,NodeId defId) + // resolver->insert_resolved_name(NodeId refId,NodeId defId) } void visit (AST::AssignmentExpr &expr) diff --git a/gcc/rust/resolve/rust-ast-resolve-pattern.h b/gcc/rust/resolve/rust-ast-resolve-pattern.h index a393d31..fc2da70 100644 --- a/gcc/rust/resolve/rust-ast-resolve-pattern.h +++ b/gcc/rust/resolve/rust-ast-resolve-pattern.h @@ -78,7 +78,6 @@ public: void visit (AST::IdentifierPattern &pattern) { - printf ("declaration for: %s\n", pattern.as_string ().c_str ()); // 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 (), diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h index 623fbd4..20d40f1 100644 --- a/gcc/rust/resolve/rust-ast-resolve-stmt.h +++ b/gcc/rust/resolve/rust-ast-resolve-stmt.h @@ -39,6 +39,11 @@ public: ~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 ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-expr.h b/gcc/rust/typecheck/rust-hir-type-check-expr.h index 2e715e9..32a5d8b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-expr.h +++ b/gcc/rust/typecheck/rust-hir-type-check-expr.h @@ -110,16 +110,25 @@ public: 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 (), - ref_node_id, &ref)) + def.parent, &ref)) { rust_error_at (expr.get_locus (), "reverse lookup failure"); return; } - // check if this has a type + // the base reference for this name _must_ have a type set TyTy::TyBase *lookup; if (!context->lookup_type (ref, &lookup)) { @@ -138,13 +147,19 @@ public: { switch (expr.get_lit_type ()) { - case HIR::Literal::LitType::INT: - infered = new TyTy::IntType (expr.get_mappings ().get_hirid (), - TyTy::IntType::IntKind::I32); + 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: - infered = new TyTy::BoolType (expr.get_mappings ().get_hirid ()); + case HIR::Literal::LitType::BOOL: { + auto ok = context->lookup_builtin ("bool", &infered); + rust_assert (ok); + } break; default: diff --git a/gcc/rust/typecheck/rust-hir-type-check-item.h b/gcc/rust/typecheck/rust-hir-type-check-item.h index 29d6db6..ab964a9 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-item.h +++ b/gcc/rust/typecheck/rust-hir-type-check-item.h @@ -66,6 +66,7 @@ public: 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 ()); diff --git a/gcc/rust/typecheck/rust-hir-type-check-stmt.h b/gcc/rust/typecheck/rust-hir-type-check-stmt.h index 39c48f0..ccf1138 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-stmt.h +++ b/gcc/rust/typecheck/rust-hir-type-check-stmt.h @@ -36,6 +36,11 @@ public: 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; diff --git a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h index c15aaef..25e6c0b 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-toplevel.h +++ b/gcc/rust/typecheck/rust-hir-type-check-toplevel.h @@ -44,9 +44,18 @@ public: else ret_type = TypeCheckType::Resolve (function.return_type.get ()); - std::vector params; + std::vector params; for (auto ¶m : function.function_params) - params.push_back (TypeCheckType::Resolve (param.type.get ())); + { + // 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); diff --git a/gcc/rust/typecheck/rust-hir-type-check-type.h b/gcc/rust/typecheck/rust-hir-type-check-type.h index d8721a3..beab77a 100644 --- a/gcc/rust/typecheck/rust-hir-type-check-type.h +++ b/gcc/rust/typecheck/rust-hir-type-check-type.h @@ -55,6 +55,7 @@ public: return; } + // reverse lookup the hir node from ast node id HirId hir_lookup; if (context->lookup_type_by_node_id (ref, &hir_lookup)) { @@ -63,7 +64,7 @@ public: return; } - // this might be a struct type reference + // this might be a struct type (TyTy::ADT) reference // TODO printf ("UNREACHABLE %s\n", path.as_string ().c_str ()); gcc_unreachable (); diff --git a/gcc/rust/typecheck/rust-hir-type-check.h b/gcc/rust/typecheck/rust-hir-type-check.h index 5a8abe1..6deecdd 100644 --- a/gcc/rust/typecheck/rust-hir-type-check.h +++ b/gcc/rust/typecheck/rust-hir-type-check.h @@ -33,6 +33,7 @@ public: ~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); diff --git a/gcc/rust/typecheck/rust-tyctx.cc b/gcc/rust/typecheck/rust-tyctx.cc index 195291e..8869e34 100644 --- a/gcc/rust/typecheck/rust-tyctx.cc +++ b/gcc/rust/typecheck/rust-tyctx.cc @@ -35,11 +35,23 @@ 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) { - printf ("inserting builtin: hir %u node %u -> %s\n", id, ref, - type->as_string ().c_str ()); node_id_refs[ref] = id; resolved[id] = type; builtins.push_back (std::unique_ptr (type)); diff --git a/gcc/rust/typecheck/rust-tyty-rules.h b/gcc/rust/typecheck/rust-tyty-rules.h index 375d909..372229b 100644 --- a/gcc/rust/typecheck/rust-tyty-rules.h +++ b/gcc/rust/typecheck/rust-tyty-rules.h @@ -155,8 +155,8 @@ public: TyBase *combine (TyBase *other) { - other->accept_vis (*this); - return resolved; + // we only case about the base type of a param + return base->get_base_type ()->combine (other); } private: diff --git a/gcc/rust/typecheck/rust-tyty.cc b/gcc/rust/typecheck/rust-tyty.cc index 2124408..4a36d4f 100644 --- a/gcc/rust/typecheck/rust-tyty.cc +++ b/gcc/rust/typecheck/rust-tyty.cc @@ -99,7 +99,7 @@ ParamType::accept_vis (TyVisitor &vis) std::string ParamType::as_string () const { - return "(" + type->as_string () + ")"; + return "(" + identifier + " :" + type->as_string () + ")"; } TyBase * diff --git a/gcc/rust/typecheck/rust-tyty.h b/gcc/rust/typecheck/rust-tyty.h index 688643c..4e04490 100644 --- a/gcc/rust/typecheck/rust-tyty.h +++ b/gcc/rust/typecheck/rust-tyty.h @@ -54,12 +54,12 @@ public: virtual void accept_vis (TyVisitor &vis) = 0; - virtual bool is_unit () const { return false; } - 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) {} @@ -95,46 +95,51 @@ public: TyBase *combine (TyBase *other) override; }; -class FnType : public TyBase +class ParamType : public TyBase { public: - FnType (HirId ref, std::vector params, TyBase *type) - : TyBase (ref, TypeKind::FNDEF), params (params), type (type) + 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 *return_type () { return type; } - TyBase *combine (TyBase *other) override; - size_t num_params () const { return params.size (); } + std::string get_identifier () const { return identifier; } - TyBase *param_at (size_t idx) { return params[idx]; } - - TyBase *get_return_type () { return type; } + TyBase *get_base_type () { return type; } private: - std::vector params; + std::string identifier; TyBase *type; }; -class ParamType : public TyBase +class FnType : public TyBase { public: - ParamType (HirId ref, TyBase *type) - : TyBase (ref, TypeKind::PARAM), type (type) + FnType (HirId ref, std::vector 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 params; TyBase *type; }; diff --git a/gcc/rust/util/rust-hir-map.cc b/gcc/rust/util/rust-hir-map.cc index 70c59f3..bdf487e 100644 --- a/gcc/rust/util/rust-hir-map.cc +++ b/gcc/rust/util/rust-hir-map.cc @@ -305,6 +305,55 @@ Mappings::lookup_hir_type (CrateNum crateNum, HirId id) } 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) { @@ -377,5 +426,22 @@ Mappings::lookup_location (CrateNum crate, HirId id) 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 index 7fc8777..a400265 100644 --- a/gcc/rust/util/rust-hir-map.h +++ b/gcc/rust/util/rust-hir-map.h @@ -115,6 +115,12 @@ public: 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 cb); @@ -127,6 +133,12 @@ public: 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 (); @@ -145,6 +157,8 @@ private: std::map > hirItemMappings; std::map > hirTypeMappings; std::map > hirExprMappings; + std::map > hirStmtMappings; + std::map > hirParamMappings; // location info std::map > locations; -- cgit v1.1