diff options
Diffstat (limited to 'gcc/rust/resolve')
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-base.h | 258 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-expr.h | 98 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-item.h | 68 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-pattern.h | 97 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-stmt.h | 59 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-toplevel.h | 54 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve-type.h | 66 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.cc | 245 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-ast-resolve.h | 50 | ||||
-rw-r--r-- | gcc/rust/resolve/rust-name-resolver.h | 211 |
10 files changed, 1206 insertions, 0 deletions
diff --git a/gcc/rust/resolve/rust-ast-resolve-base.h b/gcc/rust/resolve/rust-ast-resolve-base.h new file mode 100644 index 0000000..cc60055 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-base.h @@ -0,0 +1,258 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_BASE_H +#define RUST_AST_RESOLVE_BASE_H + +#include "rust-ast-visitor.h" +#include "rust-name-resolver.h" + +#include "rust-diagnostics.h" +#include "rust-location.h" + +namespace Rust { +namespace Resolver { + +class ResolverBase : public AST::ASTVisitor +{ +public: + virtual ~ResolverBase () {} + + // visitor impl + // rust-ast.h + // virtual void visit(AttrInput& attr_input); + // virtual void visit(TokenTree& token_tree); + // virtual void visit(MacroMatch& macro_match); + virtual void visit (AST::Token &tok) {} + virtual void visit (AST::DelimTokenTree &delim_tok_tree) {} + virtual void visit (AST::AttrInputMetaItemContainer &input) {} + // virtual void visit(MetaItem& meta_item) {} + // void vsit(Stmt& stmt) {} + // virtual void visit(Expr& expr) {} + virtual void visit (AST::IdentifierExpr &ident_expr) {} + // virtual void visit(Pattern& pattern) {} + // virtual void visit(Type& type) {} + // virtual void visit(TypeParamBound& type_param_bound) {} + virtual void visit (AST::Lifetime &lifetime) {} + // virtual void visit(GenericParam& generic_param) {} + virtual void visit (AST::LifetimeParam &lifetime_param) {} + // virtual void visit(TraitItem& trait_item) {} + // virtual void visit(InherentImplItem& inherent_impl_item) {} + // virtual void visit(TraitImplItem& trait_impl_item) {} + virtual void visit (AST::MacroInvocationSemi ¯o) {} + + // rust-path.h + virtual void visit (AST::PathInExpression &path) {} + virtual void visit (AST::TypePathSegment &segment) {} + virtual void visit (AST::TypePathSegmentGeneric &segment) {} + virtual void visit (AST::TypePathSegmentFunction &segment) {} + virtual void visit (AST::TypePath &path) {} + virtual void visit (AST::QualifiedPathInExpression &path) {} + virtual void visit (AST::QualifiedPathInType &path) {} + + // rust-expr.h + virtual void visit (AST::LiteralExpr &expr) {} + virtual void visit (AST::AttrInputLiteral &attr_input) {} + virtual void visit (AST::MetaItemLitExpr &meta_item) {} + virtual void visit (AST::MetaItemPathLit &meta_item) {} + virtual void visit (AST::BorrowExpr &expr) {} + virtual void visit (AST::DereferenceExpr &expr) {} + virtual void visit (AST::ErrorPropagationExpr &expr) {} + virtual void visit (AST::NegationExpr &expr) {} + virtual void visit (AST::ArithmeticOrLogicalExpr &expr) {} + virtual void visit (AST::ComparisonExpr &expr) {} + virtual void visit (AST::LazyBooleanExpr &expr) {} + virtual void visit (AST::TypeCastExpr &expr) {} + virtual void visit (AST::AssignmentExpr &expr) {} + virtual void visit (AST::CompoundAssignmentExpr &expr) {} + virtual void visit (AST::GroupedExpr &expr) {} + // virtual void visit(ArrayElems& elems) {} + virtual void visit (AST::ArrayElemsValues &elems) {} + virtual void visit (AST::ArrayElemsCopied &elems) {} + virtual void visit (AST::ArrayExpr &expr) {} + virtual void visit (AST::ArrayIndexExpr &expr) {} + virtual void visit (AST::TupleExpr &expr) {} + virtual void visit (AST::TupleIndexExpr &expr) {} + virtual void visit (AST::StructExprStruct &expr) {} + // virtual void visit(StructExprField& field) {} + virtual void visit (AST::StructExprFieldIdentifier &field) {} + virtual void visit (AST::StructExprFieldIdentifierValue &field) {} + virtual void visit (AST::StructExprFieldIndexValue &field) {} + virtual void visit (AST::StructExprStructFields &expr) {} + virtual void visit (AST::StructExprStructBase &expr) {} + virtual void visit (AST::StructExprTuple &expr) {} + virtual void visit (AST::StructExprUnit &expr) {} + // virtual void visit(EnumExprField& field) {} + virtual void visit (AST::EnumExprFieldIdentifier &field) {} + virtual void visit (AST::EnumExprFieldIdentifierValue &field) {} + virtual void visit (AST::EnumExprFieldIndexValue &field) {} + virtual void visit (AST::EnumExprStruct &expr) {} + virtual void visit (AST::EnumExprTuple &expr) {} + virtual void visit (AST::EnumExprFieldless &expr) {} + virtual void visit (AST::CallExpr &expr) {} + virtual void visit (AST::MethodCallExpr &expr) {} + virtual void visit (AST::FieldAccessExpr &expr) {} + virtual void visit (AST::ClosureExprInner &expr) {} + virtual void visit (AST::BlockExpr &expr) {} + virtual void visit (AST::ClosureExprInnerTyped &expr) {} + virtual void visit (AST::ContinueExpr &expr) {} + virtual void visit (AST::BreakExpr &expr) {} + virtual void visit (AST::RangeFromToExpr &expr) {} + virtual void visit (AST::RangeFromExpr &expr) {} + virtual void visit (AST::RangeToExpr &expr) {} + virtual void visit (AST::RangeFullExpr &expr) {} + virtual void visit (AST::RangeFromToInclExpr &expr) {} + virtual void visit (AST::RangeToInclExpr &expr) {} + virtual void visit (AST::ReturnExpr &expr) {} + virtual void visit (AST::UnsafeBlockExpr &expr) {} + virtual void visit (AST::LoopExpr &expr) {} + virtual void visit (AST::WhileLoopExpr &expr) {} + virtual void visit (AST::WhileLetLoopExpr &expr) {} + virtual void visit (AST::ForLoopExpr &expr) {} + virtual void visit (AST::IfExpr &expr) {} + virtual void visit (AST::IfExprConseqElse &expr) {} + virtual void visit (AST::IfExprConseqIf &expr) {} + virtual void visit (AST::IfExprConseqIfLet &expr) {} + virtual void visit (AST::IfLetExpr &expr) {} + virtual void visit (AST::IfLetExprConseqElse &expr) {} + virtual void visit (AST::IfLetExprConseqIf &expr) {} + virtual void visit (AST::IfLetExprConseqIfLet &expr) {} + // virtual void visit(MatchCase& match_case) {} + // virtual void visit (AST::MatchCaseBlockExpr &match_case) {} + // virtual void visit (AST::MatchCaseExpr &match_case) {} + virtual void visit (AST::MatchExpr &expr) {} + virtual void visit (AST::AwaitExpr &expr) {} + virtual void visit (AST::AsyncBlockExpr &expr) {} + + // rust-item.h + virtual void visit (AST::TypeParam ¶m) {} + // virtual void visit(WhereClauseItem& item) {} + virtual void visit (AST::LifetimeWhereClauseItem &item) {} + virtual void visit (AST::TypeBoundWhereClauseItem &item) {} + virtual void visit (AST::Method &method) {} + virtual void visit (AST::ModuleBodied &module) {} + virtual void visit (AST::ModuleNoBody &module) {} + virtual void visit (AST::ExternCrate &crate) {} + // virtual void visit(UseTree& use_tree) {} + virtual void visit (AST::UseTreeGlob &use_tree) {} + virtual void visit (AST::UseTreeList &use_tree) {} + virtual void visit (AST::UseTreeRebind &use_tree) {} + virtual void visit (AST::UseDeclaration &use_decl) {} + virtual void visit (AST::Function &function) {} + virtual void visit (AST::TypeAlias &type_alias) {} + virtual void visit (AST::StructStruct &struct_item) {} + virtual void visit (AST::TupleStruct &tuple_struct) {} + virtual void visit (AST::EnumItem &item) {} + virtual void visit (AST::EnumItemTuple &item) {} + virtual void visit (AST::EnumItemStruct &item) {} + virtual void visit (AST::EnumItemDiscriminant &item) {} + virtual void visit (AST::Enum &enum_item) {} + virtual void visit (AST::Union &union_item) {} + virtual void visit (AST::ConstantItem &const_item) {} + virtual void visit (AST::StaticItem &static_item) {} + virtual void visit (AST::TraitItemFunc &item) {} + virtual void visit (AST::TraitItemMethod &item) {} + virtual void visit (AST::TraitItemConst &item) {} + virtual void visit (AST::TraitItemType &item) {} + virtual void visit (AST::Trait &trait) {} + virtual void visit (AST::InherentImpl &impl) {} + virtual void visit (AST::TraitImpl &impl) {} + // virtual void visit(ExternalItem& item) {} + virtual void visit (AST::ExternalStaticItem &item) {} + virtual void visit (AST::ExternalFunctionItem &item) {} + virtual void visit (AST::ExternBlock &block) {} + + // rust-macro.h + virtual void visit (AST::MacroMatchFragment &match) {} + virtual void visit (AST::MacroMatchRepetition &match) {} + virtual void visit (AST::MacroMatcher &matcher) {} + virtual void visit (AST::MacroRulesDefinition &rules_def) {} + virtual void visit (AST::MacroInvocation ¯o_invoc) {} + virtual void visit (AST::MetaItemPath &meta_item) {} + virtual void visit (AST::MetaItemSeq &meta_item) {} + virtual void visit (AST::MetaWord &meta_item) {} + virtual void visit (AST::MetaNameValueStr &meta_item) {} + virtual void visit (AST::MetaListPaths &meta_item) {} + virtual void visit (AST::MetaListNameValueStr &meta_item) {} + + // rust-pattern.h + virtual void visit (AST::LiteralPattern &pattern) {} + virtual void visit (AST::IdentifierPattern &pattern) {} + virtual void visit (AST::WildcardPattern &pattern) {} + // virtual void visit(RangePatternBound& bound) {} + virtual void visit (AST::RangePatternBoundLiteral &bound) {} + virtual void visit (AST::RangePatternBoundPath &bound) {} + virtual void visit (AST::RangePatternBoundQualPath &bound) {} + virtual void visit (AST::RangePattern &pattern) {} + virtual void visit (AST::ReferencePattern &pattern) {} + // virtual void visit(StructPatternField& field) {} + virtual void visit (AST::StructPatternFieldTuplePat &field) {} + virtual void visit (AST::StructPatternFieldIdentPat &field) {} + virtual void visit (AST::StructPatternFieldIdent &field) {} + virtual void visit (AST::StructPattern &pattern) {} + // virtual void visit(TupleStructItems& tuple_items) {} + virtual void visit (AST::TupleStructItemsNoRange &tuple_items) {} + virtual void visit (AST::TupleStructItemsRange &tuple_items) {} + virtual void visit (AST::TupleStructPattern &pattern) {} + // virtual void visit(TuplePatternItems& tuple_items) {} + virtual void visit (AST::TuplePatternItemsMultiple &tuple_items) {} + virtual void visit (AST::TuplePatternItemsRanged &tuple_items) {} + virtual void visit (AST::TuplePattern &pattern) {} + virtual void visit (AST::GroupedPattern &pattern) {} + virtual void visit (AST::SlicePattern &pattern) {} + + // rust-stmt.h + virtual void visit (AST::EmptyStmt &stmt) {} + virtual void visit (AST::LetStmt &stmt) {} + virtual void visit (AST::ExprStmtWithoutBlock &stmt) {} + virtual void visit (AST::ExprStmtWithBlock &stmt) {} + + // rust-type.h + virtual void visit (AST::TraitBound &bound) {} + virtual void visit (AST::ImplTraitType &type) {} + virtual void visit (AST::TraitObjectType &type) {} + virtual void visit (AST::ParenthesisedType &type) {} + virtual void visit (AST::ImplTraitTypeOneBound &type) {} + virtual void visit (AST::TraitObjectTypeOneBound &type) {} + virtual void visit (AST::TupleType &type) {} + virtual void visit (AST::NeverType &type) {} + virtual void visit (AST::RawPointerType &type) {} + virtual void visit (AST::ReferenceType &type) {} + virtual void visit (AST::ArrayType &type) {} + virtual void visit (AST::SliceType &type) {} + virtual void visit (AST::InferredType &type) {} + virtual void visit (AST::BareFunctionType &type) {} + +protected: + ResolverBase (NodeId parent) + : resolver (Resolver::get ()), resolved_node (UNKNOWN_NODEID), + parent (parent), locus (Location ()) + {} + + bool resolved () const { return resolved_node != UNKNOWN_NODEID; } + + Resolver *resolver; + NodeId resolved_node; + NodeId parent; + Location locus; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_BASE_H diff --git a/gcc/rust/resolve/rust-ast-resolve-expr.h b/gcc/rust/resolve/rust-ast-resolve-expr.h new file mode 100644 index 0000000..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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_EXPR_H +#define RUST_AST_RESOLVE_EXPR_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class ResolveExpr : public ResolverBase +{ +public: + static void go (AST::Expr *expr, NodeId parent) + { + ResolveExpr resolver (parent); + expr->accept_vis (resolver); + }; + + ~ResolveExpr () {} + + void visit (AST::PathInExpression &expr) + { + if (resolver->get_name_scope ().lookup (expr.as_string (), &resolved_node)) + { + 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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_ITEM_H +#define RUST_AST_RESOLVE_ITEM_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" +#include "rust-ast-resolve-type.h" +#include "rust-ast-resolve-pattern.h" + +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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_PATTERN_H +#define RUST_AST_RESOLVE_PATTERN_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class ResolvePattern : public ResolverBase +{ +public: + static void go (AST::Pattern *pattern, NodeId parent) + { + ResolvePattern resolver (parent); + + pattern->accept_vis (resolver); + if (resolver.resolved_node == UNKNOWN_NODEID) + { + rust_error_at (resolver.locus, "failed to resolve pattern %s", + pattern->as_string ().c_str ()); + } + }; + + ~ResolvePattern () {} + + void visit (AST::IdentifierPattern &pattern) + { + if (resolver->get_name_scope ().lookup (pattern.get_ident (), + &resolved_node)) + { + resolver->insert_resolved_name (pattern.get_node_id (), resolved_node); + resolver->insert_new_definition (pattern.get_node_id (), + Definition{pattern.get_node_id (), + parent}); + } + } + +private: + ResolvePattern (NodeId parent) : ResolverBase (parent) {} +}; + +class PatternDeclaration : public ResolverBase +{ +public: + static void go (AST::Pattern *pattern, NodeId parent) + { + PatternDeclaration resolver (parent); + + pattern->accept_vis (resolver); + if (resolver.resolved_node != UNKNOWN_NODEID) + { + // print both locations?! + rust_error_at (resolver.locus, "duplicate pattern %s", + pattern->as_string ().c_str ()); + } + }; + + ~PatternDeclaration () {} + + void visit (AST::IdentifierPattern &pattern) + { + // if we have a duplicate id this then allows for shadowing correctly + // as new refs to this decl will match back here so it is ok to overwrite + resolver->get_name_scope ().insert (pattern.get_ident (), + pattern.get_node_id ()); + resolver->insert_new_definition (pattern.get_node_id (), + Definition{pattern.get_node_id (), + parent}); + } + +private: + PatternDeclaration (NodeId parent) : ResolverBase (parent) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_PATTERN_H diff --git a/gcc/rust/resolve/rust-ast-resolve-stmt.h b/gcc/rust/resolve/rust-ast-resolve-stmt.h new file mode 100644 index 0000000..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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_STMT_H +#define RUST_AST_RESOLVE_STMT_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" +#include "rust-ast-resolve-type.h" +#include "rust-ast-resolve-pattern.h" +#include "rust-ast-resolve-expr.h" + +namespace Rust { +namespace Resolver { + +class ResolveStmt : public ResolverBase +{ +public: + static void go (AST::Stmt *stmt, NodeId parent) + { + ResolveStmt resolver (parent); + stmt->accept_vis (resolver); + }; + + ~ResolveStmt () {} + + void visit (AST::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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_TOPLEVEL_H +#define RUST_AST_RESOLVE_TOPLEVEL_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class ResolveTopLevel : public ResolverBase +{ +public: + static void go (AST::Item *item) + { + ResolveTopLevel resolver; + item->accept_vis (resolver); + }; + + ~ResolveTopLevel () {} + + void visit (AST::Function &function) + { + // function_names are simple std::String identifiers so this can be a + // NodeId mapping to the Function node + resolver->get_name_scope ().insert (function.get_function_name (), + function.get_node_id ()); + } + +private: + ResolveTopLevel () : ResolverBase (UNKNOWN_NODEID) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_TOPLEVEL_H diff --git a/gcc/rust/resolve/rust-ast-resolve-type.h b/gcc/rust/resolve/rust-ast-resolve-type.h new file mode 100644 index 0000000..3cffa77 --- /dev/null +++ b/gcc/rust/resolve/rust-ast-resolve-type.h @@ -0,0 +1,66 @@ +// Copyright (C) 2020 Free Software Foundation, Inc. + +// This file is part of GCC. + +// GCC is free software; you can redistribute it and/or modify it under +// the terms of the GNU General Public License as published by the Free +// Software Foundation; either version 3, or (at your option) any later +// version. + +// GCC is distributed in the hope that it will be useful, but WITHOUT ANY +// WARRANTY; without even the implied warranty of MERCHANTABILITY or +// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License +// for more details. + +// You should have received a copy of the GNU General Public License +// along with GCC; see the file COPYING3. If not see +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_TYPE_H +#define RUST_AST_RESOLVE_TYPE_H + +#include "rust-ast-resolve-base.h" +#include "rust-ast-full.h" + +namespace Rust { +namespace Resolver { + +class ResolveType : public ResolverBase +{ +public: + static void go (AST::Type *type, NodeId parent) + { + ResolveType resolver (parent); + + type->accept_vis (resolver); + if (resolver.resolved_node == UNKNOWN_NODEID) + { + rust_error_at (resolver.locus, "failed to resolve type %s", + type->as_string ().c_str ()); + } + }; + + ~ResolveType () {} + + virtual void visit (AST::TypePath &path) + { + // this will need changed to handle mod/crate/use globs and look + // at the segments in granularity + locus = path.get_locus (); + if (resolver->get_type_scope ().lookup (path.as_string (), &resolved_node)) + { + resolver->insert_resolved_type (path.get_node_id (), resolved_node); + resolver->insert_new_definition (path.get_node_id (), + Definition{path.get_node_id (), + parent}); + } + } + +private: + ResolveType (NodeId parent) : ResolverBase (parent) {} +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_TYPE_H diff --git a/gcc/rust/resolve/rust-ast-resolve.cc b/gcc/rust/resolve/rust-ast-resolve.cc new file mode 100644 index 0000000..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 +// <http://www.gnu.org/licenses/>. + +#include "rust-ast-resolve.h" +#include "rust-ast-resolve-toplevel.h" +#include "rust-ast-resolve-item.h" +#include "rust-ast-full.h" + +#define MKBUILTIN_TYPE(_X, _R) \ + do \ + { \ + AST::PathIdentSegment seg (_X); \ + auto typePath = ::std::unique_ptr<AST::TypePathSegment> ( \ + new AST::TypePathSegment (::std::move (seg), false, \ + Linemap::predeclared_location ())); \ + ::std::vector< ::std::unique_ptr<AST::TypePathSegment> > segs; \ + segs.push_back (::std::move (typePath)); \ + auto builtin_type \ + = new AST::TypePath (::std::move (segs), \ + Linemap::predeclared_location (), false); \ + _R.push_back (builtin_type); \ + } \ + 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<AST::TypePath *> & +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 +// <http://www.gnu.org/licenses/>. + +#ifndef RUST_AST_RESOLVE_H +#define RUST_AST_RESOLVE_H + +#include "rust-name-resolver.h" +#include "rust-ast-full.h" +#include "rust-hir-map.h" + +namespace Rust { +namespace Resolver { + +class NameResolution +{ +public: + static void Resolve (AST::Crate &crate); + + static NameResolution *get (); + + ~NameResolution () {} + +private: + void go (AST::Crate &crate); + + NameResolution (); + + Resolver *resolver; + Analysis::Mappings *mappings; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_AST_RESOLVE_H diff --git a/gcc/rust/resolve/rust-name-resolver.h b/gcc/rust/resolve/rust-name-resolver.h new file mode 100644 index 0000000..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 +// <http://www.gnu.org/licenses/>. + +#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<std::string, NodeId> mappings; + std::set<NodeId> decls_within_rib; +}; + +class Scope +{ +public: + Scope (CrateNum crate_num) : crate_num (crate_num) {} + ~Scope () {} + + void insert (std::string ident, NodeId id) + { + peek ()->insert_name (ident, id); + } + + bool lookup (std::string ident, NodeId *id) + { + NodeId lookup = UNKNOWN_NODEID; + iterate ([&] (Rib *r) mutable -> bool { + if (r->lookup_name (ident, &lookup)) + return false; + return true; + }); + + *id = lookup; + return lookup != UNKNOWN_NODEID; + } + + void iterate (std::function<bool (Rib *)> cb) + { + for (auto it = stack.rbegin (); it != stack.rend (); ++it) + { + if (!cb (*it)) + return; + } + } + + Rib *peek () { return stack.back (); } + + void push (NodeId id) { stack.push_back (new Rib (get_crate_num (), id)); } + + Rib *pop () + { + Rib *r = peek (); + stack.pop_back (); + return r; + } + + CrateNum get_crate_num () const { return crate_num; } + +private: + CrateNum crate_num; + std::vector<Rib *> stack; +}; + +// This can map simple NodeIds for names to their parent node +// for example: +// +// var x = y + 1; +// +// say y has node id=1 and the plus_expression has id=2 +// then the Definition will have +// Definition { node=1, parent=2 } +// this will be used later to gather the ribs for the type inferences context +// +// if parent is UNKNOWN_NODEID then this is a root declaration +// say the var_decl hasa node_id=4; +// the parent could be a BLOCK_Expr node_id but lets make it UNKNOWN_NODE_ID so +// we know when it terminates +struct Definition +{ + NodeId node; + NodeId parent; + // add kind ? +}; + +class Resolver +{ +public: + static Resolver *get (); + ~Resolver () {} + + // these builtin types + void insert_builtin_types (Rib *r); + + // these will be required for type resolution passes to + // map back to tyty nodes + std::vector<AST::TypePath *> &get_builtin_types (); + + void push_new_name_rib (Rib *r); + void push_new_type_rib (Rib *r); + + bool find_name_rib (NodeId id, Rib **rib); + bool find_type_rib (NodeId id, Rib **rib); + + void insert_new_definition (NodeId id, Definition def); + bool lookup_definition (NodeId id, Definition *def); + + void insert_resolved_name (NodeId refId, NodeId defId); + bool lookup_resolved_name (NodeId refId, NodeId *defId); + + void insert_resolved_type (NodeId refId, NodeId defId); + bool lookup_resolved_type (NodeId refId, NodeId *defId); + + // proxy for scoping + Scope &get_name_scope () { return name_scope; } + Scope &get_type_scope () { return type_scope; } + + NodeId get_global_type_node_id () { return global_type_node_id; } + +private: + Resolver (); + + void generate_builtins (); + + Analysis::Mappings *mappings; + + std::vector<AST::TypePath *> builtins; + + Scope name_scope; + Scope type_scope; + + NodeId global_type_node_id; + + // map a AST Node to a Rib + std::map<NodeId, Rib *> name_ribs; + std::map<NodeId, Rib *> type_ribs; + + // map any Node to its Definition + // ie any name or type usage + std::map<NodeId, Definition> name_definitions; + + // Rust uses DefIds to namespace these under a crate_num + // but then it uses the def_collector to assign local_defids + // to each ast node as well. not sure if this is going to fit + // with gcc very well to compile a full crate in one go but we will + // see. + + // these are of the form ref->Def-NodeId + // we need two namespaces one for names and ones for types + std::map<NodeId, NodeId> resolved_names; + std::map<NodeId, NodeId> resolved_types; + + std::map<NodeId, std::set<NodeId> > nameDefNodeIdToRibs; + std::map<NodeId, std::set<NodeId> > typeDefNodeIdToRibs; +}; + +} // namespace Resolver +} // namespace Rust + +#endif // RUST_NAME_RESOLVER_H |