From 651ab293f3bfa117dae618edb9a4a9f328e07a91 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Thu, 18 Feb 2016 18:41:39 +1100 Subject: Random commit --- src/ast/ast.cpp | 33 ++++++++++--- src/ast/ast.hpp | 5 +- src/ast/path.cpp | 5 ++ src/convert/resolve.cpp | 127 ++++++++++++++++++++++++++++++++++++++++-------- src/dump_as_rust.cpp | 6 ++- src/main.cpp | 33 ++++++++++++- src/parse/root.cpp | 12 ----- 7 files changed, 178 insertions(+), 43 deletions(-) (limited to 'src') diff --git a/src/ast/ast.cpp b/src/ast/ast.cpp index 7ab461d5..7d9e16c5 100644 --- a/src/ast/ast.cpp +++ b/src/ast/ast.cpp @@ -217,6 +217,16 @@ void Crate::post_parse() }; iterate_module(m_root_module, cb); iterate_module(g_compiler_module, cb); + + // Create a map of inherent impls + for( const auto& impl : m_impl_index ) + { + if( impl->def().trait().is_valid() == false ) + { + auto& ent = m_impl_map[impl->def().type()]; + ent.push_back( impl ); + } + } } void Crate::iterate_functions(fcn_visitor_t* visitor) @@ -286,24 +296,31 @@ bool Crate::check_impls_wildcard(const Path& trait, const TypeRef& type) const } -::std::vector Crate::find_inherent_impls(const TypeRef& type) const +bool Crate::find_inherent_impls(const TypeRef& type, ::std::function )> callback) const { assert( !type.is_type_param() ); - ::std::vector ret; - for( auto implptr : m_impl_index ) { Impl& impl = *implptr; - DEBUG("- " << impl.def()); - ::std::vector out_params; - if( impl.def().matches(out_params, AST::Path(), type) ) + if( impl.def().trait().is_valid() ) + { + // Trait + } + else { - ret.push_back( ImplRef(impl, out_params) ); + DEBUG("- " << impl.def()); + ::std::vector out_params; + if( impl.def().matches(out_params, AST::Path(), type) ) + { + if( callback(impl, out_params) ) { + return true; + } + } } } - return ret; + return false; } ::rust::option Crate::find_impl(const Path& trait, const TypeRef& type) const diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index 3b510168..8e6f0361 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -819,6 +819,8 @@ struct ImplRef class Crate: public Serialisable { +public: + ::std::map< TypeRef, ::std::vector > m_impl_map; ::std::vector m_impl_index; ::std::vector m_neg_impl_index; @@ -848,7 +850,8 @@ public: bool is_trait_implicit(const Path& trait) const; - ::std::vector find_inherent_impls(const TypeRef& type) const; + //::std::vector find_inherent_impls(const TypeRef& type) const; + bool find_inherent_impls(const TypeRef& type, ::std::function )>) const; ::rust::option find_impl(const Path& trait, const TypeRef& type) const; bool find_impl(const Path& trait, const TypeRef& type, Impl** out_impl, ::std::vector* out_prams=nullptr) const; const ::rust::option get_impl(const Path& trait, const TypeRef& type) { diff --git a/src/ast/path.cpp b/src/ast/path.cpp index 1703da53..9ad36515 100644 --- a/src/ast/path.cpp +++ b/src/ast/path.cpp @@ -335,6 +335,9 @@ bool Path::is_concrete() const /// cause two different paths to look the same. int Path::equal_no_generic(const Path& x) const { + if( m_class.is_Invalid() && x.m_class.is_Invalid() ) + return 0; + DEBUG("equal_no_generic(this = " << *this << ", x = " << x << ")"); if( m_class.tag() != x.m_class.tag() ) return -1; if( m_crate != x.m_crate ) @@ -435,6 +438,8 @@ void Path::print_pretty(::std::ostream& os, bool is_type_context) const TU_MATCH(Path::Class, (m_class), (ent), (Invalid, os << "/*inv*/"; + // NOTE: Don't print the binding for invalid paths + return ; ), (Local, // Only print comment if there's no binding diff --git a/src/convert/resolve.cpp b/src/convert/resolve.cpp index 0e5b9598..5072f57f 100644 --- a/src/convert/resolve.cpp +++ b/src/convert/resolve.cpp @@ -89,7 +89,7 @@ public: void handle_path_abs__into_ufcs(const Span& span, AST::Path& path, unsigned slice_from, unsigned split_point); void handle_path_ufcs(const Span& span, AST::Path& path, CASTIterator::PathMode mode); void handle_path_rel(const Span& span, AST::Path& path, CASTIterator::PathMode mode); - bool find_trait_item(const Span& span, const AST::Path& path, AST::Trait& trait, const ::std::string& item_name, bool& out_is_method, AST::Path& out_trait_path); + bool find_trait_item(const Span& span, const AST::Path& path, AST::Trait& trait, const ::std::string& item_name, bool& out_is_method, const void*& out_ptr, AST::Path& out_trait_path); virtual void handle_type(TypeRef& type) override; virtual void handle_expr(AST::ExprNode& node) override; @@ -152,6 +152,7 @@ private: ::std::vector< ::std::pair > inscope_traits() const { ::std::vector< ::std::pair > ret; + DEBUG("m_module_path = " << m_module_path); for( auto it = m_scope_stack.rbegin(); it != m_scope_stack.rend(); ++it ) { for( const auto& t : it->traits ) { @@ -159,7 +160,33 @@ private: //assert(t.first.binding().is_Trait()); ret.push_back(t); } + if( it->module ) { + for( const auto& t : it->module->traits() ) { + auto trait_path = it->module_path + t.name; + DEBUG("t = " << trait_path); + ::std::pair tr(trait_path, t.data); + ret.push_back( tr ); + } + } + } + + for( const auto& t : m_module->traits() ) { + auto trait_path = m_module_path + t.name; + DEBUG("(mod) t = " << trait_path); + ::std::pair tr(trait_path, t.data); + ret.push_back( tr ); + } + for( const auto& i : m_module->imports() ) { + if( i.data.binding().is_Trait() ) + { + auto& t = *i.data.binding().as_Trait().trait_; + + DEBUG("(use) t = " << i.data); + ::std::pair tr(i.data, t); + ret.push_back( tr ); + } } + return ret; } @@ -828,6 +855,7 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera } else { this->handle_path_abs__into_ufcs(span, path, slice_from, i+1); + this->handle_path_ufcs(span, path, mode); // Explicit return - rebase slicing is already done return ; } @@ -851,6 +879,23 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera (Trait, const auto& t = item; DEBUG("Found trait"); + auto& node_args = nodes[i].args(); + if( mode == MODE_TYPE ) + { + const auto& params = t.params(); + if( params.ty_params().size() != node_args.size() ) + { + if( node_args.size() == 0 ) + { + while( node_args.size() < params.ty_params().size() ) + node_args.push_back( params.ty_params()[node_args.size()].get_default() ); + } + else + { + ERROR(span, E0000, "Incorrect number of type parameters"); + } + } + } if( is_last ) { //check_param_counts(t.params(), expect_params, nodes[i]); path.bind_trait(t); @@ -858,6 +903,7 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera } else { this->handle_path_abs__into_ufcs(span, path, slice_from, i+1); + this->handle_path_ufcs(span, path, mode); // Explicit return - rebase slicing is already done return ; } @@ -867,6 +913,22 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera (Struct, const auto& str = item; DEBUG("Found struct"); + auto& node_args = nodes[i].args(); + if( mode == MODE_TYPE ) + { + if( str.params().ty_params().size() != node_args.size() ) + { + if( node_args.size() == 0 ) + { + while( node_args.size() < str.params().ty_params().size() ) + node_args.push_back( str.params().ty_params()[node_args.size()].get_default() ); + } + else + { + ERROR(span, E0000, "Incorrect number of type parameters"); + } + } + } if( is_last ) { //check_param_counts(str.params(), expect_params, nodes[i]); path.bind_struct(str, node.args()); @@ -874,6 +936,7 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera } else { this->handle_path_abs__into_ufcs(span, path, slice_from, i+1); + this->handle_path_ufcs(span, path, mode); // Explicit return - rebase slicing is already done return ; } @@ -890,6 +953,7 @@ void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTItera } else { this->handle_path_abs__into_ufcs(span, path, slice_from, i+1); + this->handle_path_ufcs(span, path, mode); // Explicit return - rebase slicing is already done return ; } @@ -1014,7 +1078,7 @@ void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIter // 1. Search inherent impls // 2. If doing a late pass (after module-level names are resolved) search for traits if( this->m_second_pass ) { - #if 0 + #if 1 const ::std::string& item_name = info.nodes[0].name(); DEBUG("Searching for matching trait for '"<(m_self_type.back().as_Trait().trait); bool is_method; + const void* ptr; AST::Path found_trait_path; - if( this->find_trait_item(span, p, t, item_name, is_method, found_trait_path) ) { + if( this->find_trait_item(span, p, t, item_name, is_method, ptr, found_trait_path) ) { if( is_method ) { if( info.nodes.size() != 1 ) ERROR(path.span(), E0000, "CPathResolver::handle_path_ufcs - Sub-nodes to method"); + auto f = reinterpret_cast(ptr); + path.bind_function(*f, path.nodes()[0].args()); } else { if( info.nodes.size() != 1 ) throw ParseError::Todo("CPathResolver::handle_path_ufcs - Sub nodes on associated type"); + auto t = reinterpret_cast(ptr); + path.bind_type_alias(*t); } *info.trait = TypeRef( mv$(found_trait_path) ); } @@ -1054,6 +1123,7 @@ void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIter } else if( info.type->is_type_param() ) { + #if 0 DEBUG("Checking applicable generic bounds"); const auto& tp = *info.type->type_params_ptr(); assert(&tp != nullptr); @@ -1098,34 +1168,47 @@ void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIter throw ParseError::Todo( FMT("CPathResolver::handle_path_ufcs - UFCS, find trait for generic matching '" << item_name << "'") ); // - re-handle, to ensure that the bound is resolved handle_type(*info.trait); + #endif } else { + const auto& name = path.nodes()[0].name(); DEBUG("(maybe) known type"); // Iterate all inherent impls - for( auto impl : m_crate.find_inherent_impls(*info.type) ) { - IF_OPTION_SOME(item, impl.find_named_item(item_name), { - DEBUG("Found matching inherent impl"); - *info.trait = TypeRef(TypeRef::TagInvalid()); - return ; - }) - } + DEBUG("Searching for inherent impls on " << *info.type); + bool found = m_crate.find_inherent_impls( *info.type, [&](const AST::Impl& impl, ::std::vector _) -> bool { + DEBUG("Searching impl " << impl); + for( const auto& fcn : impl.functions() ) + { + if( fcn.name == name) { + path.bind_function(fcn.data, path.nodes()[0].args()); + info.trait = make_unique_ptr( TypeRef(TypeRef::TagInvalid()) ); + return true; + } + } + return false; + }); + if( found ) + return ; + + DEBUG("Searching traits"); // Iterate all traits in scope, and find one that is implemented for this type // - TODO: Iterate traits to find match for for( const auto& trait_ref : this->inscope_traits() ) { const auto& trait_p = trait_ref.first; const auto& trait = trait_ref.second; + DEBUG("Searching trait: " << trait_p); bool is_fcn; if( trait.has_named_item(item_name, is_fcn) ) { - IF_OPTION_SOME(impl, m_crate.find_impl( trait_p, *info.type ), { + IF_OPTION_SOME(impl, m_crate.find_impl( trait_p, *info.type ), *info.trait = TypeRef( trait_p ); return ; - }) + ) } } - throw ParseError::Todo( FMT("CPathResolver::handle_path_ufcs - UFCS, find trait, for type " << *info.type) ); + TODO(span, "CPathResolver::handle_path_ufcs - UFCS, find trait, for type " << *info.type << " - name='"<(st.binding().as_Trait().trait_); - if( this->find_trait_item(span, st, super_t, item_name, out_is_method, out_trait_path) ) { + if( this->find_trait_item(span, st, super_t, item_name, out_is_method, out_ptr, out_trait_path) ) { DEBUG("path = " << path << ", super_t.params() = " << super_t.params() << ", out_trait_path = " << out_trait_path); // - out_trait_path.resolve_args([&](const char* name) { + out_trait_path.resolve_args([&](const char* name) -> TypeRef { int idx = trait.params().find_name(name); if(idx < 0) ERROR(st.span(), E0000, "Parameter " << name << " not found"); + if(static_cast(idx) >= path.nodes().back().args().size()) + ERROR(st.span(), E0000, "Path '"< 0) { m_os << " = " << i.m_value; } m_os << ",\n"; + idx ++; } dec_indent(); m_os << indent() << "}\n"; diff --git a/src/main.cpp b/src/main.cpp index b8b661cc..0e0ad016 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -31,6 +31,14 @@ struct ProgramParams { static const unsigned int EMIT_C = 0x1; static const unsigned int EMIT_AST = 0x2; + enum eLastStage { + STAGE_PARSE, + STAGE_EXPAND, + STAGE_RESOLVE, + STAGE_TYPECK, + STAGE_BORROWCK, + STAGE_ALL, + } last_stage = STAGE_ALL; const char *infile = NULL; ::std::string outfile; @@ -68,10 +76,15 @@ int main(int argc, char *argv[]) AST::Crate crate = CompilePhase("Parse", [&]() { return Parse_Crate(params.infile); }); + + if( params.emit_flags == ProgramParams::STAGE_PARSE ) { + return 0; + } // Iterate all items in the AST, applying syntax extensions CompilePhaseV("Decorators", [&]() { Process_Decorators(crate); + Process_Synexts(crate); }); // Run a quick post-parse pass @@ -84,7 +97,11 @@ int main(int argc, char *argv[]) CompilePhaseV("Temp output - Parsed", [&]() { Dump_Rust( FMT(params.outfile << "_0_pp.rs").c_str(), crate ); }); - + + if( params.emit_flags == ProgramParams::STAGE_EXPAND ) { + return 0; + } + // Resolve names to be absolute names (include references to the relevant struct/global/function) // - This does name checking on types and free functions. // - Resolves all identifiers/paths to references @@ -210,6 +227,20 @@ ProgramParams::ProgramParams(int argc, char *argv[]) exit(1); } } + else if( strcmp(arg, "--stop-after") == 0 ) { + if( i == argc - 1 ) { + // TODO: BAIL! + exit(1); + } + + arg = argv[++i]; + if( strcmp(arg, "parse") == 0 ) + this->last_stage = STAGE_PARSE; + else { + ::std::cerr << "Unknown argument to --stop-after : '" << arg << "'" << ::std::endl; + exit(1); + } + } else { exit(1); } diff --git a/src/parse/root.cpp b/src/parse/root.cpp index f7d82987..5ba66dbc 100644 --- a/src/parse/root.cpp +++ b/src/parse/root.cpp @@ -1715,18 +1715,6 @@ AST::Crate Parse_Crate(::std::string mainfile) // TODO: } } - - if( crate.m_load_std ) - { - // Load the standard library (add 'extern crate std;') - crate.load_extern_crate("std"); - rootmod.add_ext_crate("std", "std"); - rootmod.add_macro_import(crate, "std", ""); - // Prelude imports are handled in Parse_ModRoot - } - - // Include the std if the 'no_std' attribute was absent - // - First need to load the std macros, then can import the prelude Parse_ModRoot(lex, crate, rootmod, NULL, mainpath); -- cgit v1.2.3