From eba9d8f840a5b81f0188d109e63631c9a34c28e9 Mon Sep 17 00:00:00 2001 From: John Hodge Date: Sun, 22 May 2016 13:49:45 +0800 Subject: Clean up dead code (both useless code, and stuff that will be rewritten for HIR) --- Makefile | 5 - src/ast/ast.hpp | 3 - src/ast/crate.cpp | 22 - src/ast/crate.hpp | 1 - src/ast/provided_module.cpp | 59 -- src/convert/ast_iterate.cpp | 552 ------------ src/convert/ast_iterate.hpp | 80 -- src/convert/decorators.cpp | 78 -- src/convert/resolve.cpp | 1856 -------------------------------------- src/convert/typecheck_bounds.cpp | 58 -- src/convert/typecheck_expr.cpp | 609 ------------- src/convert/typecheck_params.cpp | 344 ------- src/main.cpp | 8 - 13 files changed, 3675 deletions(-) delete mode 100644 src/ast/provided_module.cpp delete mode 100644 src/convert/ast_iterate.cpp delete mode 100644 src/convert/ast_iterate.hpp delete mode 100644 src/convert/decorators.cpp delete mode 100644 src/convert/resolve.cpp delete mode 100644 src/convert/typecheck_bounds.cpp delete mode 100644 src/convert/typecheck_expr.cpp delete mode 100644 src/convert/typecheck_params.cpp diff --git a/Makefile b/Makefile index 23d7cac5..e8b1d58e 100644 --- a/Makefile +++ b/Makefile @@ -29,7 +29,6 @@ BIN := bin/mrustc$(EXESUF) OBJ := main.o macros.o types.o serialise.o OBJ += span.o rc_string.o OBJ += ast/ast.o ast/crate.o ast/path.o ast/expr.o ast/pattern.o -OBJ += ast/provided_module.o OBJ += parse/parseerror.o parse/lex.o parse/token.o OBJ += parse/root.o parse/paths.o parse/types.o parse/expr.o parse/pattern.o parse/macro_rules.o OBJ += expand/mod.o expand/macro_rules.o expand/cfg.o @@ -42,10 +41,6 @@ OBJ += hir/from_ast.o hir/from_ast_expr.o OBJ += hir/crate_ptr.o hir/type_ptr.o hir/expr_ptr.o OBJ += hir/type.o hir/path.o hir/expr.o OBJ += dump_as_rust.o -OBJ += convert/ast_iterate.o -#OBJ += convert/decorators.o -#OBJ += convert/resolve.o -OBJ += convert/typecheck_bounds.o convert/typecheck_params.o convert/typecheck_expr.o PCHS := ast/ast.hpp diff --git a/src/ast/ast.hpp b/src/ast/ast.hpp index b7601192..b7de73ac 100644 --- a/src/ast/ast.hpp +++ b/src/ast/ast.hpp @@ -713,8 +713,5 @@ public: } }; -extern AST::Module g_compiler_module; -extern void AST_InitProvidedModule(); - #endif // AST_HPP_INCLUDED diff --git a/src/ast/crate.cpp b/src/ast/crate.cpp index 699bd288..d40879f3 100644 --- a/src/ast/crate.cpp +++ b/src/ast/crate.cpp @@ -45,28 +45,6 @@ void Crate::load_externs() iterate_module(m_root_module, cb); } -void Crate::index_impls() -{ - // Iterate all modules, grabbing pointers to all impl blocks - auto cb = [this](Module& mod){ - for( auto& impl : mod.impls() ) - m_impl_index.push_back( &impl ); - for( auto& impl : mod.neg_impls() ) - m_neg_impl_index.push_back( &impl ); - }; - 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) { diff --git a/src/ast/crate.hpp b/src/ast/crate.hpp index a25d2480..dbb9ca0d 100644 --- a/src/ast/crate.hpp +++ b/src/ast/crate.hpp @@ -45,7 +45,6 @@ public: /// Load referenced crates void load_externs(); - void index_impls(); bool is_trait_implicit(const Path& trait) const; diff --git a/src/ast/provided_module.cpp b/src/ast/provided_module.cpp deleted file mode 100644 index e36784f0..00000000 --- a/src/ast/provided_module.cpp +++ /dev/null @@ -1,59 +0,0 @@ -/* - */ -#include "ast.hpp" - -void AST_InitProvidedModule_Impls(); - -AST::Module g_compiler_module; -AST::Path g_copy_marker_path; -AST::Path g_sized_marker_path; - -void AST_InitProvidedModule() -{ - // "struct str([u8])" - ::std::vector fields; - fields.push_back( AST::StructItem(AST::MetaItems(), false, "", TypeRef(TypeRef::TagUnsizedArray(), Span(), TypeRef(Span(), CORETYPE_U8))) ); - g_compiler_module.add_struct(true, "str", AST::Struct(AST::GenericParams(), mv$(fields)), AST::MetaItems()); - - AST_InitProvidedModule_Impls(); -} - -void AST_InitProvidedModule_Impls() -{ - if( !g_copy_marker_path.is_valid() ) { - g_copy_marker_path = AST::Path( "", {AST::PathNode("marker"),AST::PathNode("Copy")} ); - } - - if( !g_sized_marker_path.is_valid() ) { - g_sized_marker_path = AST::Path( "", {AST::PathNode("marker"),AST::PathNode("Sized")} ); - } - - #define impl(trait, type) \ - g_compiler_module.add_impl(AST::Impl(AST::MetaItems(), AST::GenericParams(), type, trait)) - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_U8)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_U16)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_U32)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_U64)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_UINT)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_I8)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_I16)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_I32)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_I64)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_INT)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_F32)); - impl(g_copy_marker_path, TypeRef(Span(), CORETYPE_F64)); - - // A hacky default impl of 'Sized', with a negative impl on [T] - impl(g_sized_marker_path, TypeRef()); - - { - AST::GenericParams tps; - tps.add_ty_param( AST::TypeParam("T") ); - g_compiler_module.add_neg_impl(AST::ImplDef( - AST::MetaItems(), ::std::move(tps), - g_sized_marker_path, - TypeRef(TypeRef::TagUnsizedArray(), Span(), TypeRef(TypeRef::TagArg(), "T")) - )); - } -} - diff --git a/src/convert/ast_iterate.cpp b/src/convert/ast_iterate.cpp deleted file mode 100644 index 7e70f1f0..00000000 --- a/src/convert/ast_iterate.cpp +++ /dev/null @@ -1,552 +0,0 @@ -/** - */ -#include "ast_iterate.hpp" -#include "../ast/ast.hpp" - -void CASTIterator::handle_path(AST::Path& path, CASTIterator::PathMode pm) -{ -} -void CASTIterator::handle_type(TypeRef& type) -{ - TRACE_FUNCTION_F("type = " << type); - - TU_MATCH(TypeData, (type.m_data), (ent), - (None), - (Any), - (Unit), - (Macro), - (Primitive), - (Path, - handle_path(ent.path, MODE_TYPE); - ), - (Tuple, - for(auto& subtype : ent.inner_types) - handle_type(subtype); - ), - (Borrow, - handle_type(*ent.inner); - ), - (Pointer, - handle_type(*ent.inner); - ), - (Array, - handle_type(*ent.inner); - ), - (Function, - handle_type(*ent.info.m_rettype); - for(auto& arg : ent.info.m_arg_types) - handle_type(arg); - ), - (Generic), - (TraitObject, - for(auto& trait : ent.traits) - handle_path(trait, MODE_TYPE); - ) - ) -} -void CASTIterator::handle_expr(AST::ExprNode& node) -{ -} -void CASTIterator::handle_params(AST::GenericParams& params) -{ - DEBUG("params"); - for( auto& param : params.ty_params() ) - { - handle_type(param.get_default()); - local_type( param.name(), TypeRef(TypeRef::TagArg(), param.name(), params) ); - } - DEBUG("Bounds"); - for( auto& bound : params.bounds() ) - { - TU_MATCH( AST::GenericBound, (bound), (ent), - (Lifetime, - DEBUG("namecheck lifetime bounds?"); - ), - (TypeLifetime, - handle_type(ent.type); - DEBUG("namecheck lifetime bounds?"); - ), - (IsTrait, - handle_type(ent.type); - // TODO: Define HRLs - push_self(ent.type); - handle_path(ent.trait, CASTIterator::MODE_TYPE); - pop_self(); - ), - (MaybeTrait, - handle_type(ent.type); - push_self(ent.type); - handle_path(ent.trait, CASTIterator::MODE_TYPE); - pop_self(); - // TODO: Process trait, ensuring that it's a valid lang item - ), - (NotTrait, - handle_type(ent.type); - push_self(ent.type); - handle_path(ent.trait, CASTIterator::MODE_TYPE); - pop_self(); - ), - (Equality, - handle_type(ent.type); - handle_type(ent.replacement); - ) - ) - } -} - - -void CASTIterator::start_scope() -{ - INDENT(); -} -void CASTIterator::local_type(::std::string name, TypeRef type) -{ - DEBUG("type " << name << " = " << type); -} -void CASTIterator::local_variable(bool is_mut, ::std::string name, const TypeRef& type) -{ - DEBUG( (is_mut ? "mut " : "") << name << " : " << type ); -} -void CASTIterator::local_use(::std::string name, AST::Path path) -{ - DEBUG( name << " = " << path ); -} -void CASTIterator::end_scope() -{ - UNINDENT(); -} - -void CASTIterator::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) -{ - //DEBUG("pat = " << pat); - // Resolve names - TU_MATCH(AST::Pattern::Data, (pat.data()), (v), - (Any, - // Wildcard, nothing to do - ), - (Macro, - // Macro, nothing really (should be impossible?) - ), - (Box, { - auto& v = pat.data().as_Box(); - if( type_hint.is_wildcard() ) - handle_pattern(*v.sub, (const TypeRef&)TypeRef()); - else { - throw ::std::runtime_error("TODO: Handle box patterns in CASTIterator::handle_pattern"); - handle_pattern(*v.sub, type_hint.inner_type()); - } - }), - (Ref, { - auto& v = pat.data().as_Ref(); - if( type_hint.is_wildcard() ) - handle_pattern(*v.sub, (const TypeRef&)TypeRef()); - else if( !type_hint.is_reference() ) - throw ::std::runtime_error( FMT("Ref pattern on non-ref value: " << type_hint) ); - else - handle_pattern(*v.sub, type_hint.inner_type()); - }), - (MaybeBind, - throw ::std::runtime_error("Calling CASTIterator::handle_pattern on MAYBE_BIND, not valid"); - ), - (Value, - TU_IFLET(AST::Pattern::Value, v.start, Named, e, - handle_path(e, CASTIterator::MODE_TYPE); - ) - TU_IFLET(AST::Pattern::Value, v.end, Named, e, - handle_path(e, CASTIterator::MODE_TYPE); - ) - ), - (Tuple, { - auto& v = pat.data().as_Tuple(); - // Tuple is handled by subpattern code - if( type_hint.is_wildcard() ) - { - for( auto& sp : v.sub_patterns ) - handle_pattern(sp, (const TypeRef&)TypeRef()); - } - else if( !type_hint.is_tuple() ) - { - throw ::std::runtime_error("Tuple pattern on non-tuple value"); - } - else - { - const auto& inner_types = type_hint.m_data.as_Tuple().inner_types; - if( inner_types.size() != v.sub_patterns.size() ) - { - throw ::std::runtime_error("Tuple pattern count doesn't match"); - } - for( unsigned int i = 0; i < v.sub_patterns.size(); i ++ ) - { - handle_pattern(v.sub_patterns[i], inner_types[i]); - } - } - }), - (Struct, { - auto& v = pat.data().as_Struct(); - handle_path( v.path, CASTIterator::MODE_TYPE ); - if( type_hint.is_wildcard() ) - { - for( auto& sp : v.sub_patterns ) - handle_pattern(sp.second, (const TypeRef&)TypeRef()); - } - else if( !type_hint.is_path() ) - { - throw ::std::runtime_error("Tuple struct pattern on non-tuple value"); - } - else - { - auto& path = type_hint.m_data.as_Path().path; - if( path.is_bound() ) { - throw ::std::runtime_error("TODO: Typecheck/iterate struct pattern (with known type)"); - } - else { - for( auto& sp : v.sub_patterns ) - handle_pattern(sp.second, (const TypeRef&)TypeRef()); - } - } - }), - (StructTuple, { - auto& v = pat.data().as_StructTuple(); - // Resolve the path! - handle_path( v.path, CASTIterator::MODE_TYPE ); - // Handle sub-patterns - if( type_hint.is_wildcard() ) - { - for( auto& sp : v.sub_patterns ) - handle_pattern(sp, (const TypeRef&)TypeRef()); - } - else if( !type_hint.is_path() ) - { - throw ::std::runtime_error("Tuple struct pattern on non-tuple value"); - } - else - { - auto& hint_path = type_hint.path(); - auto& pat_path = v.path; - const auto& hint_binding = hint_path.binding(); - const auto& pat_binding = pat_path.binding(); - DEBUG("Pat: " << pat_path << ", Type: " << type_hint.path()); - TU_MATCH_DEF( AST::PathBinding, (hint_binding), (info), - ( - throw ::std::runtime_error(FMT("Bad type in tuple struct pattern : " << type_hint.path())) - ), - (Unbound, - throw ::std::runtime_error("Unbound path in pattern"); - ), - (Enum, - // The pattern's path must refer to a variant of the hint path - // - Actual type params are checked by the 'handle_pattern_enum' code - if( !pat_binding.is_EnumVar() ) - throw ::std::runtime_error(FMT("Paths in pattern are invalid")); - if( pat_binding.as_EnumVar().enum_ != info.enum_ ) - throw ::std::runtime_error(FMT("Paths in pattern are invalid")); - const auto& enm = *pat_binding.as_EnumVar().enum_; - auto idx = pat_binding.as_EnumVar().idx; - auto& var = enm.variants().at(idx); - handle_pattern_enum(pat_path[-2].args(), hint_path[-1].args(), enm.params(), var, v.sub_patterns); - ) - ) - } - }), - (Slice, - TypeRef null_type; - const auto* inner_type = &null_type; - if( !type_hint.is_wildcard() ) - { - TU_MATCH_DEF( TypeData, (type_hint.m_data), (v), - ( - ERROR(Span(), E0000, "Slice pattern on non-slice/array"); - ), - (Array, - inner_type = v.inner.get(); - ), - (Borrow, - if( v.inner->is_wildcard() ) { - } - else if( v.inner->m_data.is_Array() ) { - inner_type = v.inner->m_data.as_Array().inner.get(); - } - else { - // TODO: Deref more? - ERROR(Span(), E0000, "Slice pattern on non-slice/array"); - } - ) - ) - } - for( auto& sp : v.leading ) - handle_pattern(sp, *inner_type); - for( auto& sp : v.trailing ) - handle_pattern(sp, *inner_type); - ) - ) - // Extract bindings and add to namespace - if( pat.binding().size() > 0 ) - { - // TODO: Mutable bindings - if(pat.binding() != "_") - { - local_variable( false, pat.binding(), type_hint ); - } - } -} -void CASTIterator::handle_pattern_enum( - ::std::vector& pat_args, const ::std::vector& hint_args, - const AST::GenericParams& enum_params, const AST::EnumVariant& var, - ::std::vector& sub_patterns - ) -{ - // This implementation doesn't attempt to do anything with types, just propagates _ - for( auto& sp : sub_patterns ) - handle_pattern(sp, (const TypeRef&)TypeRef()); -} - -void CASTIterator::handle_module(AST::Path path, AST::Module& mod) -{ - INDENT(); - start_scope(); - - for( auto& item : mod.items() ) - { - TU_MATCH(::AST::Item, (item.data), (e), - (None, - // Explicitly ignored (represents a deleted item) - ), - (Crate, - // Nothing to be done - ), - (Struct, - DEBUG("Handling struct " << item.name); - handle_struct(path + item.name, e); - ), - (Enum, - DEBUG("Handling enum " << item.name); - handle_enum(path + item.name, e); - ), - (Trait, - DEBUG("Handling trait " << item.name); - handle_trait(path + item.name, e); - ), - (Type, - DEBUG("Handling alias " << item.name); - handle_alias(path + item.name, e); - ), - (Static, - DEBUG("handling static " << item.name); - handle_type(e.type()); - if( e.value().is_valid() ) - { - handle_expr(e.value().node()); - } - ), - (Function, - DEBUG("Handling function '" << item.name << "'"); - handle_function(path + item.name, e); - ), - (Module, - // Skip, done after all items - ) - ) - } - - for( auto& impl : mod.impls() ) - { - DEBUG("Handling 'impl' " << impl); - handle_impl(path, impl); - } - - // End scope before handling sub-modules - end_scope(); - - for( auto& item : mod.items() ) - { - if(!item.data.is_Module()) continue; - auto& submod = item.data.as_Module(); - DEBUG("Handling submod '" << item.name << "'"); - handle_module(path + item.name, submod); - } - unsigned int anon_mod_idx = 0; - for( auto& anonmod : mod.anon_mods() ) - { - auto& submod = *anonmod; - DEBUG("Handling submod #" << anon_mod_idx); - handle_module(path + FMT("#" << anon_mod_idx), submod); - anon_mod_idx += 1; - } - UNINDENT(); -} -void CASTIterator::handle_function(AST::Path path, AST::Function& fcn) -{ - TRACE_FUNCTION_F("path = " << path << ", fcn.params() = " << fcn.params()); - start_scope(); - - DEBUG("params"); - handle_params(fcn.params()); - - DEBUG("ret type"); - handle_type(fcn.rettype()); - - //switch( fcn.fcn_class() ) - //{ - //case AST::Function::CLASS_UNBOUND: - // break; - //case AST::Function::CLASS_REFMETHOD: - // local_variable(false, "self", TypeRef(TypeRef::TagReference(), false, TypeRef(TypeRef::TagArg(), "Self"))); - // break; - //case AST::Function::CLASS_MUTMETHOD: - // local_variable(false, "self", TypeRef(TypeRef::TagReference(), true, TypeRef(TypeRef::TagArg(), "Self"))); - // break; - //case AST::Function::CLASS_VALMETHOD: - // local_variable(false, "self", TypeRef(TypeRef::TagArg(), "Self")); - // break; - //case AST::Function::CLASS_MUTVALMETHOD: - // local_variable(true, "self", TypeRef(TypeRef::TagArg(), "Self")); - // break; - //} - - DEBUG("args"); - for( auto& arg : fcn.args() ) - { - handle_type(arg.second); - // TODO: Check if pattern is irrefutable? - handle_pattern( arg.first, arg.second ); - } - - DEBUG("code"); - if( fcn.code().is_valid() ) - { - INDENT(); - handle_expr( fcn.code().node() ); - UNINDENT(); - } - - end_scope(); -} - -void CASTIterator::handle_impl_def(AST::ImplDef& impl) -{ - // Generic params - handle_params( impl.params() ); - - // Type - handle_type( impl.type() ); - - push_self(impl.type()); - - // Trait - if( impl.trait() != AST::Path() ) - handle_path( impl.trait(), MODE_TYPE ); -} - -void CASTIterator::handle_impl(AST::Path modpath, AST::Impl& impl) -{ - start_scope(); - - handle_impl_def(impl.def()); - - // Associated types - for( auto& it : impl.items() ) - { - TU_MATCH_DEF(AST::Item, (it.data), (e), - ( - ), - (Type, - DEBUG("- Type '" << it.name << "'"); - handle_type( e.type() ); - ), - (Function, - DEBUG("- Function '" << it.name << "'"); - handle_function(AST::Path(AST::Path::TagRelative(), { AST::PathNode(it.name) }), e); - ) - ) - } - - pop_self(); - end_scope(); -} - -void CASTIterator::handle_struct(AST::Path path, AST::Struct& str) -{ - start_scope(); - handle_params( str.params() ); - TU_MATCH(AST::StructData, (str.m_data), (e), - (Tuple, - for( auto& f : e.ents ) - handle_type( f.m_type ); - ), - (Struct, - for( auto& f : e.ents ) - handle_type( f.m_type ); - ) - ) - end_scope(); -} -void CASTIterator::handle_enum(AST::Path path, AST::Enum& enm) -{ - start_scope(); - handle_params( enm.params() ); - for( auto& f : enm.variants() ) - { - TU_MATCH(AST::EnumVariantData, (f.m_data), (e), - (Value, - ), - (Tuple, - for( auto& t : e.m_sub_types ) - handle_type(t); - ), - (Struct, - for( auto& t : e.m_fields ) - handle_type(t.m_type); - ) - ) - } - end_scope(); -} -void CASTIterator::handle_trait(AST::Path path, AST::Trait& trait) -{ - start_scope(); - push_self(path, trait); - handle_params( trait.params() ); - - for( auto& st : trait.supertraits() ) { - if( st.m_class.is_Invalid() ) { - // An invalid path is used for 'static - } - else { - handle_path(st, MODE_TYPE); - } - } - - for( auto& i : trait.items() ) - { - TU_MATCH_DEF(AST::Item, (i.data), (e), - ( - ), - (Type, - // TODO: Can trait associated types have default types? - ), - (Static, - handle_type(e.type()); - ), - (Function, - handle_function( path + i.name, e ); - ) - ) - } - pop_self(); - end_scope(); -} -void CASTIterator::handle_alias(AST::Path path, AST::TypeAlias& alias) -{ - start_scope(); - handle_params( alias.params() ); - handle_type( alias.type() ); - end_scope(); -} -void CASTIterator::push_self() { -} -void CASTIterator::push_self(AST::Path path, const AST::Trait& trait) { -} -void CASTIterator::push_self(TypeRef real_type) { -} -void CASTIterator::pop_self() { -} diff --git a/src/convert/ast_iterate.hpp b/src/convert/ast_iterate.hpp deleted file mode 100644 index fc57cf57..00000000 --- a/src/convert/ast_iterate.hpp +++ /dev/null @@ -1,80 +0,0 @@ -#ifndef _AST_ITERATE_HPP_INCLUDED_ -#define _AST_ITERATE_HPP_INCLUDED_ - -#include -#include "../types.hpp" -#include "../ast/path.hpp" - -namespace AST { - -class ExprNode; -class Pattern; -class GenericParams; -class Impl; -class ImplDef; -class EnumVariant; -template struct Named; - -}; - -// Iterator for the AST, calls virtual functions on paths/types -class CASTIterator -{ -public: - enum PathMode { - MODE_EXPR, // Variables allowed - MODE_TYPE, - MODE_BIND, // Failure is allowed - }; - virtual void handle_path(AST::Path& path, PathMode mode); - virtual void handle_type(TypeRef& type); - virtual void handle_expr(AST::ExprNode& node); - - virtual void handle_params(AST::GenericParams& params); - - virtual void start_scope(); - virtual void local_type(::std::string name, TypeRef type); - virtual void local_variable(bool is_mut, ::std::string name, const TypeRef& type); - virtual void local_use(::std::string name, AST::Path path); - virtual void end_scope(); - - virtual void handle_pattern(AST::Pattern& pat, const TypeRef& type_hint); - virtual void handle_pattern_enum( - ::std::vector& pat_args, const ::std::vector& hint_args, - const AST::GenericParams& enum_params, const AST::EnumVariant& var, - ::std::vector& sub_patterns - ); - - virtual void handle_module(AST::Path path, AST::Module& mod); - - virtual void handle_function(AST::Path path, AST::Function& fcn); - virtual void handle_impl(AST::Path modpath, AST::Impl& impl); - - virtual void handle_struct(AST::Path path, AST::Struct& str); - virtual void handle_enum(AST::Path path, AST::Enum& enm); - virtual void handle_trait(AST::Path path, AST::Trait& trait); - virtual void handle_alias(AST::Path path, AST::TypeAlias& alias); - - virtual void push_self(); - virtual void push_self(AST::Path path, const AST::Trait& trait); - virtual void push_self(TypeRef real_type); - virtual void pop_self(); - -private: - void handle_impl_def(AST::ImplDef& impl); -}; - -static inline ::std::ostream& operator<<(::std::ostream& os, const CASTIterator::PathMode& mode) { - switch(mode) - { - case CASTIterator::MODE_EXPR: return os << "MODE_EXPR"; - case CASTIterator::MODE_TYPE: return os << "MODE_TYPE"; - case CASTIterator::MODE_BIND: return os << "MODE_BIND"; - } - return os; -} - - - -#endif - diff --git a/src/convert/decorators.cpp b/src/convert/decorators.cpp deleted file mode 100644 index 06716e5f..00000000 --- a/src/convert/decorators.cpp +++ /dev/null @@ -1,78 +0,0 @@ -/* - * MRustC - Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * convert/decorators.cpp - * - Handles #[...] item decorators by delegating - */ -#include "ast_iterate.hpp" -#include "../ast/ast.hpp" -#include "../ast/crate.hpp" -#include -#include // C++11, hashmap -#include - -::std::unordered_map< ::std::string, ::std::unique_ptr > g_decorators; - -template -void Decorator_Apply(AST::Crate& crate, AST::Module& mod, const AST::MetaItems& attrs, const AST::Path& path, T& ent) -{ - // For all attributes on the item, search for a handler and call handler - for( const auto& attr : attrs.m_items ) - { - auto it = g_decorators.find(attr.name()); - if( it != g_decorators.end() ) - { - const CDecoratorHandler& handler = *it->second; - - handler.handle_item(crate, mod, attr, path, ent); - } - else { - } - } -} - -class CProcessor: - public CASTIterator -{ - AST::Crate& m_crate; - ::std::vector m_modstack; -public: - CProcessor(AST::Crate& crate): - m_crate(crate) - {} - - void handle_module(AST::Path path, AST::Module& mod) override - { - m_modstack.push_back(&mod); - CASTIterator::handle_module(mv$(path), mod); - m_modstack.pop_back(); - } - - void handle_struct(AST::Path path, AST::Struct& str) override - { - Decorator_Apply(m_crate, *m_modstack.back(), str.attrs(), path, str); - } - - void handle_trait(AST::Path path, AST::Trait& tr) override - { - Decorator_Apply(m_crate, *m_modstack.back(), tr.attrs(), path, tr); - } -}; - -void Register_Synext_Decorator(::std::string name, ::std::unique_ptr handler) -{ - auto res = g_decorators.insert( ::std::make_pair(name, mv$(handler)) ); - if( res.second == false ) - { - DEBUG("Duplicate definition of decorator '"<C converter - * - By John Hodge (Mutabah / thePowersGang) - * - * convert/resolve.cpp - * - Resolve names into absolute format - * - * - Converts all paths into a canonical format (absolute, local, or UFCS) - */ -#include "../common.hpp" -#include "../ast/ast.hpp" -#include "../ast/crate.hpp" -#include "../parse/parseerror.hpp" -#include "ast_iterate.hpp" - -// ==================================================================== -// -- Path resolver (converts paths to absolute form) -// ==================================================================== -class CPathResolver: - public CASTIterator -{ - const AST::Crate& m_crate; - AST::Module* m_module; - AST::Path m_module_path; - ::std::vector< ::std::pair > m_module_stack; - - struct LocalItem - { - enum Type { - TYPE, - VAR, - } type; - ::std::string name; - TypeRef tr; - - LocalItem(): - type(VAR), name() - {} - LocalItem(Type t, ::std::string name, TypeRef tr=TypeRef()): - type(t), - name( ::std::move(name) ), - tr( ::std::move(tr) ) - {} - - friend ::std::ostream& operator<<(::std::ostream& os, const LocalItem& x) { - if( x.name == "" ) - return os << "#"; - else if( x.type == TYPE ) - return os << "type '" << x.name << "' = " << x.tr; - else - return os << "var '" << x.name << "'"; - } - }; - ::std::vector< LocalItem > m_locals; - - struct Scope { - unsigned int module_idx; - AST::Module *module; // can be NULL - AST::Path module_path; - ::std::vector< ::std::string > locals; - - ::std::vector< ::std::pair > traits; - }; - ::std::vector m_scope_stack; - - - TAGGED_UNION(SelfType, None, - (None, struct {}), - (Type, struct { - TypeRef type; - }), - (Trait, struct { - AST::Path path; - const AST::Trait* trait; - }) - ); - ::std::vector m_self_type; - - friend class CResolvePaths_NodeVisitor; - -public: - bool m_second_pass = false; - - CPathResolver(const AST::Crate& crate); - - void handle_params(AST::GenericParams& params) override; - - virtual void handle_path(AST::Path& path, CASTIterator::PathMode mode) override; - void handle_path_abs(const Span& span, AST::Path& path, CASTIterator::PathMode mode); - 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, const void*& out_ptr, AST::Path& out_trait_path); - virtual void handle_type(TypeRef& type) override; - virtual void handle_expr(AST::ExprNode& node) override; - - virtual void handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) override; - virtual void handle_module(AST::Path path, AST::Module& mod) override; - virtual void handle_trait(AST::Path path, AST::Trait& trait) override; - virtual void handle_function(AST::Path path, AST::Function& fcn) override; - - virtual void start_scope() override; - virtual void local_type(::std::string name, TypeRef type) override { - DEBUG("(name = " << name << ", type = " << type << ")"); - if( lookup_local(LocalItem::TYPE, name).is_some() ) { - // Shadowing the type... check for recursion by doing a resolve check? - type.resolve_args([&](const char *an){ if(an == name) return TypeRef(name+" "); else return TypeRef(an); }); - } - m_locals.push_back( LocalItem(LocalItem::TYPE, ::std::move(name), ::std::move(type)) ); - } - virtual void local_variable(bool _is_mut, ::std::string name, const TypeRef& _type) override { - assert(m_scope_stack.size() > 0); - m_scope_stack.back().locals.push_back( ::std::move(name) ); - } - virtual void local_use(::std::string name, AST::Path path) override { - assert( !path.binding().is_Unbound() ); - if( path.binding().is_Trait() ) { - m_scope_stack.back().traits.push_back( ::std::pair(path, *path.binding().as_Trait().trait_) ); - } - } - virtual void end_scope() override; - - ::rust::option lookup_local(LocalItem::Type type, const ::std::string& name) const; - - bool find_local_item(const Span& span, AST::Path& path, const ::std::string& name, bool allow_variables); - //bool find_local_item(AST::Path& path, bool allow_variables); - bool find_mod_item(const Span& span, AST::Path& path, const ::std::string& name); - bool find_self_mod_item(const Span& span, AST::Path& path, const ::std::string& name); - bool find_super_mod_item(const Span& span, AST::Path& path, const ::std::string& name); - bool find_type_param(const ::std::string& name); - - virtual void push_self() override { - m_self_type.push_back( SelfType::make_None({}) ); - } - virtual void push_self(AST::Path path, const AST::Trait& trait) override { - m_self_type.push_back( SelfType::make_Trait( {path, &trait} ) ); - } - virtual void push_self(TypeRef real_type) override { - // 'Self' must be resolved because ... - //if( real_type.is_path() && real_type.path().binding().is_Unbound() ) { - // assert( !"Unbound path passed to push_self" ); - //} - m_self_type.push_back( SelfType::make_Type( {real_type} ) ); - } - virtual void pop_self() override { - m_self_type.pop_back(); - } - - // TODO: Handle a block and obtain the local module (if any) -private: - void handle_path_int(const Span& span, AST::Path& path, CASTIterator::PathMode mode); - - ::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 ) { - DEBUG("t = " << t.first); - //assert(t.first.binding().is_Trait()); - ret.push_back(t); - } - if( it->module ) { - for( const auto& i : it->module->items() ) { - if( !i.data.is_Trait() ) continue ; - const auto& t = i.data.as_Trait(); - auto trait_path = it->module_path + i.name; - DEBUG("t = " << trait_path); - ret.push_back( ::std::pair(trait_path, t) ); - } - } - } - - for( const auto& i : m_module->items() ) { - if( !i.data.is_Trait() ) continue ; - const auto& t = i.data.as_Trait(); - auto trait_path = m_module_path + i.name; - DEBUG("(mod) t = " << trait_path); - ret.push_back( ::std::pair(trait_path, t) ); - } - for( const auto& i : m_module->imports() ) { - if( i.data.path.binding().is_Trait() ) - { - auto& t = *i.data.path.binding().as_Trait().trait_; - - DEBUG("(use) t = " << i.data); - ::std::pair tr(i.data.path, t); - ret.push_back( tr ); - } - } - - return ret; - } - - -}; - -// Path resolution checking -void ResolvePaths(AST::Crate& crate); -void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& modpath, AST::Module& mod); - -class CResolvePaths_NodeVisitor: - public AST::NodeVisitorDef -{ - CPathResolver& m_res; -public: - CResolvePaths_NodeVisitor(CPathResolver& res): - m_res(res) - { - } - - void visit(AST::ExprNode_Macro& node) { - BUG(node.get_pos(), "Un-resolved macro in expression"); - - //MacroExpander expanded_macro = Macro_Invoke(node.m_name.c_str(), node.m_tokens); - // TODO: Requires being able to replace the node with a completely different type of node - //node.replace( Parse_Expr0(expanded_macro) ); - } - - void visit(AST::ExprNode_NamedValue& node) { - DEBUG("ExprNode_NamedValue"); - m_res.handle_path(node.m_path, CASTIterator::MODE_EXPR); - } - void visit(AST::ExprNode_CallPath& node) { - DEBUG(node.get_pos() << " ExprNode_CallPath - " << node); - AST::NodeVisitorDef::visit(node); - m_res.handle_path(node.m_path, CASTIterator::MODE_EXPR); - } - - void visit(AST::ExprNode_Block& node) { - // If there's an inner module on this node - if( node.m_local_mod.get() ) - { - - // Add a reference to it to the parent node (add_anon_module will do dedup) - AST::Module* parent_mod_p = m_res.m_module; - for(const auto& e : m_res.m_scope_stack) - if(e.module != nullptr) - parent_mod_p = e.module; - AST::Module& parent_mod = *parent_mod_p; - auto idx = parent_mod.add_anon_module( node.m_local_mod.get() ); - - // Obtain the path - AST::Path local_path = m_res.m_module_path; - for(const auto& e : m_res.m_scope_stack ) { - if( e.module != nullptr ) { - local_path.nodes().push_back( AST::PathNode( FMT("#" << e.module_idx), {} ) ); - } - } - local_path.nodes().push_back( AST::PathNode(FMT("#" << idx), {}) ); - - // And add to the list of modules to use in lookup - m_res.m_scope_stack.push_back( {idx, node.m_local_mod.get(), local_path, {}} ); - - // Do use resolution on this module - // TODO: When is more advanced resolution done? - ResolvePaths_HandleModule_Use(m_res.m_crate, m_res.m_scope_stack.back().module_path, *node.m_local_mod); - } - else { - m_res.m_scope_stack.push_back( {0, nullptr, AST::Path(), {}} ); - } - AST::NodeVisitorDef::visit(node); - // Once done, pop the module - m_res.m_scope_stack.pop_back(); - } - - void visit(AST::ExprNode_IfLet& node) - { - DEBUG("ExprNode_IfLet"); - AST::NodeVisitor::visit(node.m_value); - - m_res.start_scope(); - m_res.handle_pattern(node.m_pattern, TypeRef()); - AST::NodeVisitor::visit(node.m_true); - m_res.end_scope(); - - AST::NodeVisitor::visit(node.m_false); - } - - void visit(AST::ExprNode_Match& node) - { - DEBUG("ExprNode_Match"); - AST::NodeVisitor::visit(node.m_val); - - for( auto& arm : node.m_arms ) - { - m_res.start_scope(); - for( auto& pat : arm.m_patterns ) - m_res.handle_pattern(pat, TypeRef()); - AST::NodeVisitor::visit(arm.m_cond); - AST::NodeVisitor::visit(arm.m_code); - m_res.end_scope(); - } - } - - void visit(AST::ExprNode_Loop& node) - { - switch( node.m_type ) - { - case AST::ExprNode_Loop::FOR: - AST::NodeVisitor::visit(node.m_cond); - m_res.start_scope(); - m_res.handle_pattern(node.m_pattern, TypeRef()); - AST::NodeVisitor::visit(node.m_code); - m_res.end_scope(); - break; - case AST::ExprNode_Loop::WHILELET: - AST::NodeVisitor::visit(node.m_cond); - m_res.start_scope(); - m_res.handle_pattern(node.m_pattern, TypeRef()); - AST::NodeVisitor::visit(node.m_code); - m_res.end_scope(); - break; - default: - AST::NodeVisitorDef::visit(node); - break; - } - } - - void visit(AST::ExprNode_LetBinding& node) - { - DEBUG("ExprNode_LetBinding"); - - AST::NodeVisitor::visit(node.m_value); - m_res.handle_type(node.m_type); - m_res.handle_pattern(node.m_pat, TypeRef()); - } - - void visit(AST::ExprNode_StructLiteral& node) override - { - DEBUG("ExprNode_StructLiteral"); - - m_res.handle_path(node.m_path, CASTIterator::MODE_EXPR); - AST::NodeVisitorDef::visit(node); - } - - void visit(AST::ExprNode_Closure& node) override - { - DEBUG("ExprNode_Closure"); - m_res.start_scope(); - for( auto& param : node.m_args ) - { - DEBUG("- ExprNode_Closure: pat=" << param.first << ", ty=" << param.second); - m_res.handle_type(param.second); - m_res.handle_pattern(param.first, param.second); - } - DEBUG("- ExprNode_Closure: rt=" << node.m_return); - m_res.handle_type(node.m_return); - AST::NodeVisitor::visit(node.m_code); - m_res.end_scope(); - } - - void visit(AST::ExprNode_Cast& node) override - { - DEBUG("ExprNode_Cast"); - m_res.handle_type(node.m_type); - AST::NodeVisitorDef::visit(node); - } - - void visit(AST::ExprNode_CallMethod& node) override - { - DEBUG("ExprNode_CallMethod"); - for( auto& arg : node.m_method.args() ) - m_res.handle_type(arg); - AST::NodeVisitorDef::visit(node); - } -}; - -/// Do simple path resolution on this path -/// - Simple involves only doing item name lookups, no checks of generic params at all or handling UFCS -void resolve_path(const Span& span, const AST::Crate& root_crate, AST::Path& path) -{ - if( !path.is_absolute() ) { - BUG(span, "Calling resolve_path on non-absolute path - " << path); - } - const AST::Module* mod = &root_crate.root_module(); - for(const auto& node : path.nodes() ) { - if( node.args().size() > 0 ) { - throw ParseError::Generic("Unexpected generic params in use path"); - } - if( mod == nullptr ) { - if( path.binding().is_Enum() ) { - auto& enm = *path.binding().as_Enum().enum_; - for(const auto& variant : enm.variants()) { - if( variant.m_name == node.name() ) { - path.bind_enum_var(enm, node.name()); - break; - } - } - if( path.binding().is_Enum() ) { - ERROR(span, E0000, "Unable to find component '" << node.name() << "' of import " << path << " (enum)" ); - } - break; - } - else { - throw ParseError::Generic("Extra path components after final item"); - } - } - auto item = mod->find_item(node.name()); - //while( item.is_None() && node.name()[0] == '#' ) { - //} - // HACK: Not actually a normal TU, but it fits the same pattern - TU_MATCH(AST::Module::ItemRef, (item), (i), - (None, - ERROR(span, E0000, "Unable to find component '" << node.name() << "' of import " << path); - ), - (Module, - mod = &i; - ), - (Crate, - mod = &root_crate.get_root_module(i); - ), - (TypeAlias, - path.bind_type_alias(i); - mod = nullptr; - ), - (Function, - path.bind_function(i); - mod = nullptr; - ), - (Trait, - path.bind_trait(i); - mod = nullptr; - ), - (Struct, - path.bind_struct(i); - mod = nullptr; - ), - (Enum, - // - Importing an enum item will be handled in the nullptr check above - path.bind_enum(i); - mod = nullptr; - ), - (Static, - path.bind_static(i); - mod = nullptr; - ), - (Use, - if(i.name == "") { - throw ParseError::Todo("Handle resolving to wildcard use in use resolution"); - } - else { - // Restart lookup using new path - } - ) - ) - } - if( mod != nullptr ) { - path.bind_module(*mod); - } -} - -CPathResolver::CPathResolver(const AST::Crate& crate): - m_crate(crate), - m_module(nullptr) -{ -} -void CPathResolver::start_scope() -{ - DEBUG(""); - m_scope_stack.push_back( {0, nullptr, AST::Path(), {}} ); - m_locals.push_back( LocalItem() ); -} -void CPathResolver::end_scope() -{ - m_scope_stack.pop_back( ); - DEBUG(m_locals.size() << " items"); - for( auto it = m_locals.end(); it-- != m_locals.begin(); ) - { - if( it->name == "" ) { - m_locals.erase(it, m_locals.end()); - return ; - } - } - m_locals.clear(); -} -// Returns the bound path for the local item -::rust::option CPathResolver::lookup_local(LocalItem::Type type, const ::std::string& src_name) const -{ - DEBUG("m_locals = [" << m_locals << "]"); - ::std::string name = src_name; - unsigned int count = 0; - while( name.size() > 0 && name.back() == ' ') { - name.pop_back(); - count ++; - } - for( auto it = m_locals.end(); it -- != m_locals.begin(); ) - { - if( it->type == type ) - { - if( it->name == name && count-- == 0 ) - return ::rust::option(*it); - } - } - return ::rust::option(); -} - -// Search relative to current module -// > Search local use definitions (function-level) -// - TODO: Local use statements (scoped) -// > Search module-level definitions -bool lookup_path_in_module(const Span& span, const AST::Crate& crate, const AST::Module& module, const AST::Path& mod_path, AST::Path& path, const ::std::string& name, bool is_leaf) -{ - TRACE_FUNCTION_F("mod_path="< UFCS: Resolve the type and trait - case AST::Path::Class::TAG_UFCS: - handle_path_ufcs(span, path, mode); - break; - // > Variable: (wait, how is this known already?) - // - 'self', 'Self' - case AST::Path::Class::TAG_Local: - DEBUG("Check local"); - if( !path.binding().is_Unbound() ) - { - DEBUG("- Path " << path << " already bound"); - } - else - { - const auto& info = path.m_class.as_Local(); - // 1. Check for local items - if( this->find_local_item(span, path, info.name, (mode == CASTIterator::MODE_EXPR)) ) { - if( path.is_absolute() ) { - handle_path_abs(span, path, mode); - } - break ; - } - else { - // No match, fall through - } - // 2. Type parameters (ONLY when in type mode) - if( mode == CASTIterator::MODE_TYPE ) { - throw ::std::runtime_error("TODO: Local in CPathResolver::handle_path_int type param"); - } - // 3. Module items - if( this->find_mod_item(span, path, info.name) ) { - handle_path_abs(span, path, mode); - break; - } - else { - } - - DEBUG("no matches found for path = " << path); - if( mode != MODE_BIND ) - throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed (Local)"); - return ; - } - if(0) - - // Unannotated relative - case AST::Path::Class::TAG_Relative: - handle_path_rel(span, path, mode); - if(0) - - // Module relative - case AST::Path::Class::TAG_Self: - { - if( this->find_self_mod_item(span, path, path[0].name()) ) { - // Fall - } - else { - DEBUG("no matches found for path = " << path); - if( mode != MODE_BIND ) - throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed"); - } - } - if(0) - // Parent module relative - // TODO: "super::" can be chained - case AST::Path::Class::TAG_Super: - { - if( this->find_super_mod_item(span, path, path[0].name()) ) { - // Fall - } - else { - DEBUG("no matches found for path = " << path); - if( mode != MODE_BIND ) - throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed"); - } - } - // Common for Relative, Self, and Super - DEBUG("Post relative resolve - path=" << path); - if( path.is_absolute() ) { - handle_path_abs(span, path, mode); - } - else { - } - return ; - } - - // TODO: Are there any reasons not to be bound at this point? - //assert( !path.binding().is_Unbound() ); -} - -// Validates all components are able to be located, and converts Trait/Struct/Enum::Item into UFCS format -void CPathResolver::handle_path_abs(const Span& span, AST::Path& path, CASTIterator::PathMode mode) -{ - //bool expect_params = false; - - if( !path.m_class.is_Absolute() ) { - BUG(span, "Non-absolute path passed to CPathResolver::handle_path_abs - path=" << path); - } - - auto& nodes = path.m_class.as_Absolute().nodes; - - unsigned int slice_from = 0; // Used when rewriting the path to be relative to its crate root - - // Iterate through nodes, starting at the root module of the specified crate - // - Locate the referenced item, and fail if any component isn't found - ::std::vector mod_stack; - const AST::Module* mod = &this->m_crate.get_root_module(path.crate()); - for(unsigned int i = 0; i < nodes.size(); i ++ ) - { - mod_stack.push_back(mod); - const bool is_last = (i+1 == nodes.size()); - const AST::PathNode& node = nodes[i]; - DEBUG("[" << i << "/"<anon_mods().at(index); - continue ; - } - - auto item_ref = mod->find_item(node.name(), is_last); // Only allow leaf nodes (functions and statics) if this is the last node - TU_MATCH( AST::Module::ItemRef, (item_ref), (item), - // Not found - (None, - // If parent node is anon, backtrack and try again - // TODO: I feel like this shouldn't be done here, instead perform this when absolutising (now that find_item is reusable) - if( i > 0 && nodes[i-1].name()[0] == '#' && nodes[i-1].name().size() > 1 ) - { - i --; - mod_stack.pop_back(); - mod = mod_stack.back(); - mod_stack.pop_back(); - nodes.erase(nodes.begin()+i); - i --; - DEBUG("Failed to locate item in nested, look upwards"); - - continue ; - } - ERROR(span, E0000, "Unable to find component '" << node.name() << "' of path " << path); - ), - // Sub-module - (Module, - DEBUG("Sub-module : " << node.name()); - if( node.args().size() ) - throw ParseError::Generic("Generic params applied to module"); - mod = &item; - ), - // Crate - (Crate, - const ::std::string& crate_name = item; - DEBUG("Extern crate '" << node.name() << "' = '" << crate_name << "'"); - if( node.args().size() ) - throw ParseError::Generic("Generic params applied to extern crate"); - path.set_crate( crate_name ); - slice_from = i+1; - mod = &this->m_crate.get_root_module(crate_name); - ), - - // Type Alias - (TypeAlias, - const auto& ta = item; - DEBUG("Type alias <"< " << ta.type()); - //if( node.args().size() != ta.params().size() ) - // throw ParseError::Generic("Param count mismatch when referencing type alias"); - // Make a copy of the path, replace params with it, then replace *this? - // - Maybe leave that up to other code? - if( is_last ) { - //check_param_counts(ta.params(), expect_params, nodes[i]); - // TODO: Bind / replace - // - Replacing requires checking type params (well, at least the count) - path.bind_type_alias(ta); - goto ret; - } - 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 ; - } - ), - - // Function - (Function, - const auto& fn = item; - DEBUG("Found function"); - if( is_last ) { - //check_param_counts(fn.params(), expect_params, nodes[i]); - path.bind_function(fn); - goto ret; - } - else { - throw ParseError::Generic("Import of function, too many extra nodes"); - } - ), - - // Trait - (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); - goto ret; - } - 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 ; - } - ), - - // Struct - (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()); - goto ret; - } - 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 ; - } - ), - - // Enum / enum variant - (Enum, - const auto& enm = item; - DEBUG("Found enum"); - if( is_last ) { - //check_param_counts(enm.params(), expect_params, nodes[i]); - path.bind_enum(enm, node.args()); - goto ret; - } - 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 ; - } - ), - - (Static, - const auto& st = item; - DEBUG("Found static/const"); - if( is_last ) { - if( node.args().size() ) - throw ParseError::Generic("Unexpected generic params on static/const"); - path.bind_static(st); - goto ret; - } - else { - throw ParseError::Generic("Binding path to static, trailing nodes"); - } - ), - - // Re-export - (Use, - const auto& imp = item; - AST::Path newpath = imp.data.path; - auto& newnodes = newpath.m_class.as_Absolute().nodes; - DEBUG("Re-exported path " << imp.data); - if( imp.name == "" ) - { - // Replace nodes 0:i-1 with source path, then recurse - for( unsigned int j = i; j < nodes.size(); j ++ ) - { - newnodes.push_back( nodes[j] ); - } - } - else - { - // replace nodes 0:i with the source path - for( unsigned int j = i+1; j < nodes.size(); j ++ ) - { - newnodes.push_back( nodes[j] ); - } - } - - DEBUG("- newpath = " << newpath); - // TODO: This should check for recursion somehow - this->handle_path_abs(span, newpath, mode); - - path = mv$(newpath); - return; - ) - ) - } - - // We only reach here if the path points to a module - path.bind_module( *mod ); -ret: - if( slice_from > 0 ) - { - DEBUG("Removing " << slice_from << " nodes to rebase path to crate root"); - nodes.erase(nodes.begin(), nodes.begin()+slice_from); - } - return ; -} -// Starting from the `slice_from`th element, take until `split_point` as the type path, and the rest of the nodes as UFCS items -void CPathResolver::handle_path_abs__into_ufcs(const Span& span, AST::Path& path, unsigned slice_from, unsigned split_point) -{ - TRACE_FUNCTION_F("(path = " << path << ", slice_from=" << slice_from << ", split_point=" << split_point << ")"); - assert(slice_from < path.size()); - assert(slice_from < split_point); - // Split point must be at most the last index - assert(split_point < path.size()); - - const auto& nodes = path.nodes(); - AST::Path type_path(path.crate(), ::std::vector( nodes.begin() + slice_from, nodes.begin() + split_point )); - for(unsigned i = split_point; i < nodes.size(); i ++) - { - DEBUG("type_path = " << type_path << ", nodes[i] = " << nodes[i]); - resolve_path(span, m_crate, type_path); - // If the type path refers to a trait, put it in the trait location - if(type_path.binding().is_Trait()) { - type_path = AST::Path(AST::Path::TagUfcs(), TypeRef(span), TypeRef(span, mv$(type_path)), {mv$(nodes[i])} ); - } - else { - type_path = AST::Path(AST::Path::TagUfcs(), TypeRef(span, mv$(type_path)), TypeRef(span), {mv$(nodes[i])} ); - } - } - - path = mv$(type_path); -} - - -/// Handles path resolution for UFCS format paths (::Item) -void CPathResolver::handle_path_ufcs(const Span& span, AST::Path& path, CASTIterator::PathMode mode) -{ - assert(path.m_class.is_UFCS()); - auto& info = path.m_class.as_UFCS(); - TRACE_FUNCTION_F("info={< " << *info.type << " as " << *info.trait << ">::" << info.nodes << "}"); - // 1. Handle sub-types - handle_type(*info.type); - handle_type(*info.trait); - - // - Some quick assertions - if( info.type->is_path() ) - { - TU_MATCH_DEF(AST::PathBinding, (info.type->path().binding()), (i), - ( - // Invalid - BUG(span, "Invalid item class for type in path " << path); - ), - //(Unbound, - // ), - //(Trait, ), - (Struct, ), - (Enum, ) - ) - } - - // 2. Handle wildcard traits (locate in inherent impl, or from an in-scope trait) - // TODO: Disabled, as it requires having all traits (semi) path resolved, so that trait resolution works cleanly - // - Impl heads and trait heads could be resolved in an earlier pass - if( info.trait->is_wildcard() ) - { - // 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 1 - const ::std::string& item_name = info.nodes[0].name(); - DEBUG("Searching for matching trait for '"< params; - if( info.type->is_type_param() && info.type->type_param() == "Self" ) - { - DEBUG("Checking Self trait and sub-traits"); - // TODO: What is "Self" here? May want to use `GenericBound`s to replace Self with the actual type when possible. - // In which case, Self will refer to "implementor of this trait". - // - Look up applicable traits for this type, using bounds (basically same as next) - assert( !m_self_type.empty() ); - assert( m_self_type.back().is_Trait() ); - AST::Path p = m_self_type.back().as_Trait().path; - handle_path(p, MODE_TYPE); - AST::Trait& t = *const_cast(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, ptr, found_trait_path) ) { - if( is_method ) { - if( info.nodes.size() != 1 ) - ERROR(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 ) - TODO(span, "CPathResolver::handle_path_ufcs - Sub nodes on associated type"); - auto t = reinterpret_cast(ptr); - path.bind_type_alias(*t); - } - *info.trait = TypeRef( span, mv$(found_trait_path) ); - } - else { - ERROR(span, E0000, "Cannot find item '" << item_name << "' on Self"); - } - } - 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); - bool success = false; - - // Enumerate bounds - for( const auto& bound : tp.bounds() ) - { - DEBUG("bound = " << bound); - TU_MATCH_DEF(AST::GenericBound, (bound), (ent), - (), - (IsTrait, - if( ent.type == *info.type ) { - auto& t = *const_cast(ent.trait.binding().as_Trait().trait_); - DEBUG("Type match, t.params() = " << t.params()); - bool is_method; - AST::Path found_trait_path; - DEBUG("find_trait_item(" << ent.trait << /*", t=" << t <<*/ ", item_name = " << item_name); - if( this->find_trait_item(span, ent.trait, t, item_name, is_method, found_trait_path) ) - { - if( is_method ) { - if( info.nodes.size() != 1 ) - throw ParseError::Generic("CPathResolver::handle_path_ufcs - Sub-nodes to method"); - } - else { - if( info.nodes.size() != 1 ) - throw ParseError::Todo("CPathResolver::handle_path_ufcs - Sub nodes on associated type"); - } - *info.trait = TypeRef( mv$(found_trait_path) ); - success = true; - break ; - } - } - else { - DEBUG("Type mismatch " << ent.type << " != " << *info.type); - } - ) - ) - } - - if( !success ) - 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 - 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& i : impl.items() ) - { - if( i.name == name ) { - TU_MATCH_DEF(AST::Item, (i.data), (e), - ( - // Ignore? - ), - (Function, - path.bind_function(e, path.nodes()[0].args()); - info.trait = make_unique_ptr( TypeRef(TypeRef::TagInvalid(), span) ); - 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 ), - *info.trait = TypeRef( span, trait_p ); - return ; - ) - } - } - - TODO(span, "CPathResolver::handle_path_ufcs - UFCS, find trait, for type " << *info.type << " - name='"<is_path() ) - { - // 1. Search for enum constructors - TU_MATCH_DEF(AST::PathBinding, (info.type->path().binding()), (i), - ( ), - (Enum, - const auto& e = *i.enum_; - for(const auto& var : e.variants()) - { - if( var.m_name == name ) { - path.bind_enum_var(e, name); - info.trait = make_unique_ptr( TypeRef(TypeRef::TagInvalid(), span) ); - return ; - } - } - ) - ) - } - } - } - else - { - #if 0 - const auto& name = path.nodes()[0].name(); - // Trait is known, need to ensure that the named item exists - assert(info.trait->path().binding().is_Trait()); - const auto &tr = *info.trait->path().binding().as_Trait().trait_; - - // TODO: Need to try super-traits AND applicable type impls - // - E.g. "impl Any {" - switch(mode) - { - case MODE_EXPR: - for( const auto& fcn : tr.functions() ) - { - DEBUG("fcn.name = " << fcn.name); - if(fcn.name == name) { - path.bind_function(fcn.data); - break; - } - } - //for( const auto& fcn : tr.constants() ) - //{ - //} - break; - case MODE_BIND: - //for( const auto& fcn : tr.constants() ) - //{ - //} - break; - case MODE_TYPE: - for( const auto& it : tr.types() ) - { - if(it.name == name) { - path.bind_type_alias(it.data); - break; - } - } - break; - } - if(mode == MODE_EXPR && path.binding().is_Unbound()) { - // TODO: Locate an 'impl Trait' block for methods - } - if(path.binding().is_Unbound()) { - ERROR(span, E0000, "Unable to locate item '" << name << "' in trait " << *info.trait << " (mode=" << mode << ")"); - } - #endif - } -} -void CPathResolver::handle_path_rel(const Span& span, AST::Path& path, CASTIterator::PathMode mode) -{ - // 1. function scopes (variables and local items) - // > Return values: name or path - { - bool allow_variables = (mode == CASTIterator::MODE_EXPR && path.is_trivial()); - if( this->find_local_item(span, path, path[0].name(), allow_variables) ) { - return ; - } - } - - // 2. Type parameters - // - Should probably check if this is expression mode, bare types are invalid there - // NOTES: - // - If the path is bare (i.e. there are no more nodes), then ensure that the mode is TYPE - // - If there are more nodes, replace with a UFCS block - { - auto tp = this->find_type_param(path[0].name()); - if( tp != false /*nullptr*/ || path[0].name() == "Self" ) - { - if(path.size() > 1) { - auto ty = TypeRef(TypeRef::TagArg(), path[0].name()); - //ty.set_span( path.span() ); - // Repalce with UFCS - auto newpath = AST::Path(AST::Path::TagUfcs(), ty, TypeRef()); - newpath.add_tailing(path); - path = mv$(newpath); - } - else { - // Mark as local - // - TODO: Not being trivial is an error, not a bug - assert( path.is_trivial() ); - path = AST::Path(AST::Path::TagLocal(), path[0].name()); - // - TODO: Need to bind this to the source parameter block - } - return ; - } - } - - // 3. current module - { - if( this->find_mod_item(span, path, path[0].name()) ) { - return ; - } - else { - } - } - - // 4. If there was no match above, and we're in bind mode, set the path to local and return - DEBUG("no matches found for path = " << path); - if( mode == MODE_BIND ) - { - // If mode == MODE_BIND, must be trivial - if( !path.is_trivial() ) - throw ParseError::Generic("CPathResolver::handle_path - Name resolution failed (non-trivial path failed to resolve in MODE_BIND)"); - path = AST::Path(AST::Path::TagLocal(), path[0].name()); - return ; - } - - // 5. Check if the unresolved name is a primitive type - { - if( path[0].name() == "str" ) { - TODO(span, "Expand `str` to internal path"); - } - else if( auto ct = coretype_fromstring(path[0].name()) ) { - auto ty = TypeRef(TypeRef::TagPrimitive(), span, ct); - auto newpath = AST::Path(AST::Path::TagUfcs(), ty, TypeRef()); - newpath.add_tailing(path); - path = mv$(newpath); - return ; - } - else { - } - } - - // Z. Otherwise, error - ERROR(span, E0000, "CPathResolver::handle_path - Name resolution failed"); -} - -bool CPathResolver::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) -{ - TRACE_FUNCTION_F("path=" << path << ", trait=..., item_name=" << item_name); - { - const auto& items = trait.items(); - auto it = ::std::find_if( items.begin(), items.end(), [&](const auto& a) { DEBUG("fcn " << a.name); return a.name == item_name; } ); - if( it != items.end() ) { - // Found it. - const auto& i = *it; - TU_MATCH_DEF(AST::Item, (i.data), (e), - ( - BUG(Span(), "Unknown item type in trait"); - ), - (Function, - out_is_method = true; - out_ptr = &e; - out_trait_path = AST::Path(path); - DEBUG("Fcn, out_trait_path = " << out_trait_path); - return true; - ), - (Type, - out_is_method = false; - out_ptr = &it->data; - out_trait_path = AST::Path(path); - DEBUG("Ty, out_trait_path = " << out_trait_path << " path=" << path); - return true; - ), - (Static, - TODO(Span(), "Handle resolving associated statics/consts in traits (CPathResolver::find_trait_item)"); - ) - ) - } - } - - for( auto& st : trait.supertraits() ) { - if(!st.is_bound()) { - handle_path(st, MODE_TYPE); - //BUG(st.span(), "Supertrait path '"<(st.binding().as_Trait().trait_); - 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) -> TypeRef { - int idx = trait.params().find_name(name); - if(idx < 0) - ERROR(span, E0000, "Parameter " << name << " not found"); - if(static_cast(idx) >= path.nodes().back().args().size()) - ERROR(span, E0000, "Path '"<path() = '" << mod->path() << "'"); - if( lookup_path_in_module(span, m_crate, *mod, *modpath, path, name, path.size()==1) ) - return true; - DEBUG("mod->path() = '" << mod->path() << "', idx = " << idx); - if( mod->is_anon() && idx > 0 ) { - idx --; - mod = m_module_stack[idx].first; - modpath = &m_module_stack[idx].second; - } - else { - break ; - } - } - return false; -} -bool CPathResolver::find_self_mod_item(const Span& span, AST::Path& path, const ::std::string& name) { - if( m_module->is_anon() ) - throw ParseError::Todo("Correct handling of 'self' in anon modules"); - - return lookup_path_in_module(span, m_crate, *m_module, m_module_path, path, name, path.size()==1); -} -bool CPathResolver::find_super_mod_item(const Span& span, AST::Path& path, const ::std::string& name) { - if( m_module->is_anon() ) - throw ParseError::Todo("Correct handling of 'super' in anon modules"); - - // 1. Construct path to parent module - AST::Path super_path = m_module_path; - super_path.nodes().pop_back(); - assert( super_path.nodes().size() > 0 ); - if( super_path.nodes().back().name()[0] == '#' ) - throw ParseError::Todo("Correct handling of 'super' in anon modules (parent is anon)"); - // 2. Resolve that path - resolve_path(span, m_crate, super_path); - // 3. Call lookup_path_in_module - assert( super_path.binding().is_Module() ); - return lookup_path_in_module(span, m_crate, *super_path.binding().as_Module().module_, super_path, path, name, path.size()==1); -} -bool CPathResolver::find_type_param(const ::std::string& name) { - for( auto it = m_locals.end(); it -- != m_locals.begin(); ) - { - if( it->type == LocalItem::TYPE ) { - if( it->name == name ) { - return true; - } - } - } - return false; -} - -void CPathResolver::handle_type(TypeRef& type) -{ - TRACE_FUNCTION_F("type = " << type); - // PROBLEM: Recursion when evaluating Self that expands to UFCS mentioning Self - // > The inner Self shouldn't be touched, but it gets hit by this method, and sudden recursion - //if( type.is_locked() ) - //{ - //} - //else - if( type.is_path() && type.path().is_trivial() ) - { - const auto& name = type.path()[0].name(); - auto opt_local = lookup_local(LocalItem::TYPE, name); - - if( opt_local.is_some() ) - { - DEBUG("Found local '" << name << "' aliasing to " << opt_local.unwrap().tr); - type = opt_local.unwrap().tr; - } - else if( name == "Self" ) - { - // TODO: Should I always resolve `Self` when it's concretely known? - // If the name was "Self", but Self isn't already defined... then we need to make it an arg? - if( this->m_self_type.empty() || this->m_self_type.back().is_None() ) { - ERROR(Span(), E0000, "Unexpected 'Self'"); - } - else { - TU_MATCH(SelfType, (this->m_self_type.back()), (ent), - (None, - assert(!"SelfType is None in CPathResolver::handle_type"); - ), - (Type, - DEBUG("Self type is " << ent.type); - type = ent.type; - return ; - ), - (Trait, - // TODO: Need to have the trait encoded in the type. To avoid interpolation and bad replacement - // - Would also reduce the need to look at the m_self_type stack - type = TypeRef(TypeRef::TagArg(), "Self"); - ) - ) - } - } - else - { - // Not a type param, fall back to other checks - } - } - else if( type.is_type_param() ) - { - const auto& name = type.type_param(); - auto opt_local = lookup_local(LocalItem::TYPE, name); - if( name == "Self" ) - { - if( m_self_type.empty() ) { - ERROR(type.span(), E0000, "Self type not set"); - } - TU_MATCH(SelfType, (m_self_type.back()), (ent), - (None, - ERROR(type.span(), E0000, "Self type not set"); - ), - (Type, - DEBUG("Self type is " << ent.type); - type = ent.type; - return ; - ), - (Trait, - // Valid... - ) - ) - } - else if( opt_local.is_some() ) - { - type = opt_local.unwrap().tr; - } - else - { - // Not a type param, fall back to other checks - throw CompileError::Generic( FMT("CPathResolver::handle_type - Invalid parameter '" << name << "'") ); - } - } - else - { - // No change - } - DEBUG("type = " << type); - - //if - - //if( type.is_type_param() && type.type_param() == "Self" ) - //{ - // auto l = lookup_local(LocalItem::TYPE, "Self"); - // if( l.is_some() ) - // { - // type = l.unwrap().tr; - // DEBUG("Replacing Self with " << type); - // // TODO: Can this recurse? - // handle_type(type); - // return ; - // } - //} - CASTIterator::handle_type(type); - DEBUG("res = " << type); -} -void CPathResolver::handle_expr(AST::ExprNode& node) -{ - CResolvePaths_NodeVisitor nv(*this); - node.visit(nv); -} - -void CPathResolver::handle_pattern(AST::Pattern& pat, const TypeRef& type_hint) -{ - TRACE_FUNCTION_F("pat = " << pat); - // Resolve "Maybe Bind" entries - if( pat.data().is_MaybeBind() ) - { - ::std::string name = pat.binding(); - // Locate a _constant_ within the current namespace which matches this name - // - Variables don't count - AST::Path newpath = AST::Path(AST::Path::TagRelative(), { AST::PathNode(name) }); - handle_path(newpath, CASTIterator::MODE_BIND); - if( newpath.is_relative() || newpath.is_trivial() ) - { - // It's a name binding (desugar to 'name @ _') - pat = AST::Pattern(); - pat.set_bind(name, AST::Pattern::BIND_MOVE, false); - } - else - { - // It's a constant (enum variant usually) - pat = AST::Pattern( - AST::Pattern::TagValue(), - AST::Pattern::Value::make_Named( mv$(newpath) ) - ); - } - } - - // hand off to original code - CASTIterator::handle_pattern(pat, type_hint); -} -void CPathResolver::handle_module(AST::Path path, AST::Module& mod) -{ - ::std::vector saved = mv$(m_scope_stack); - // NOTE: Assigning here is safe, as the CASTIterator handle_module iterates submodules as the last action - m_module = &mod; - m_module_path = AST::Path(path); - m_module_stack.push_back( ::std::make_pair(&mod, m_module_path) ); - CASTIterator::handle_module(mv$(path), mod); - m_module_stack.pop_back(); - m_scope_stack = mv$(saved); -} -void CPathResolver::handle_trait(AST::Path path, AST::Trait& trait) -{ - //path.resolve(m_crate); - - // Handle local - m_scope_stack.back().traits.push_back( ::std::pair(path, trait) ); - CASTIterator::handle_trait(path, trait); -} -void CPathResolver::handle_function(AST::Path path, AST::Function& fcn) -{ - m_scope_stack.push_back( {0, nullptr, AST::Path(), {}} ); - CASTIterator::handle_function(::std::move(path), fcn); - m_scope_stack.pop_back(); -} - - -void absolutise_path(const Span& span, const AST::Crate& crate, const AST::Module& mod, const AST::Path& modpath, AST::Path& path) -{ - // TODO: Should this code resolve encountered use statements into the real path? - TU_MATCH(AST::Path::Class, (path.m_class), (info), - (Invalid, - BUG(span, "Invalid path type encountered - Class::Invalid"); - ), - (Local, - // Known-local paths don't need to be absolutised - ), - (Absolute, - // Nothing needs to be done - ), - (Super, - // TODO: Super supports multiple instances - auto newpath = modpath; - newpath.nodes().pop_back(); - newpath += path; - DEBUG("Absolutised path " << path << " into " << newpath); - path = ::std::move(newpath); - ), - (Self, - auto modpath_tmp = modpath; - const AST::Module* mod_ptr = &mod; - while( modpath_tmp.size() > 0 && modpath_tmp.nodes().back().name()[0] == '#' ) - { - if( !mod_ptr->find_item(path.nodes()[0].name()).is_None() ) { - break ; - } - modpath_tmp.nodes().pop_back(); - resolve_path(span, crate, modpath_tmp); - DEBUG("modpath_tmp = " << modpath_tmp); - assert( modpath_tmp.binding().is_Module() ); - mod_ptr = modpath_tmp.binding().as_Module().module_; - } - auto newpath = modpath_tmp + path; - DEBUG("Absolutised path " << path << " into " << newpath); - path = ::std::move(newpath); - ), - (Relative, - auto newpath = modpath + path; - DEBUG("Absolutised path " << path << " into " << newpath); - path = ::std::move(newpath); - ), - (UFCS, - throw ParseError::Generic( FMT("Invalid path type encounted - UFCS " << path) ); - ) - ) -} - -void ResolvePaths_HandleModule_Use(const AST::Crate& crate, const AST::Path& modpath, AST::Module& mod) -{ - TRACE_FUNCTION_F("modpath = " << modpath << ", mod = {path:" << mod.path() << "}"); - ::std::vector new_imports; - for( auto& imp : mod.imports() ) - { - const Span& span = imp.data.sp; - DEBUG("p = " << imp.data); - absolutise_path(span, crate, mod, modpath, imp.data.path); - - resolve_path(span, crate, imp.data.path); - DEBUG("Resolved import : " << imp.data); - - // If wildcard, make sure it's sane - if( imp.name == "" ) - { - TU_MATCH_DEF(AST::PathBinding, (imp.data.path.binding()), (info), - ( - throw ParseError::Generic("Wildcard imports are only allowed on modules and enums"); - ), - (Unbound, - throw ParseError::BugCheck("Wildcard import path unbound after calling .resolve()"); - ), - (Module, (void)0;), - (Enum, (void)0;) - ) - } - } - - for( auto& new_imp : new_imports ) - { - //if( new_imp.binding().is_Unbound() ) { - // new_imp.resolve(crate, false); - //} - // TODO: Get attributes from the source import - mod.add_alias(false, ::AST::UseStmt(Span(), new_imp), new_imp[new_imp.size()-1].name(), ::AST::MetaItems()); - } - - for(auto& item : mod.items()) { - if( item.data.is_Module() ) { - ResolvePaths_HandleModule_Use(crate, modpath + item.name, item.data.as_Module()); - } - } -} - -void SetCrateName_Type(const AST::Crate& crate, ::std::string name, TypeRef& type) -{ - if( type.is_path() ) - { - type.path().set_crate(name); - //type.path().resolve(crate); - } -} - -void SetCrateName_Mod(const AST::Crate& crate, ::std::string name, AST::Module& mod) -{ - for(auto& item : mod.items()) { - if( item.data.is_Module() ) { - SetCrateName_Mod(crate, name, item.data.as_Module()); - } - } - // Imports 'use' statements - for(auto& imp : mod.imports()) - { - imp.data.path.set_crate(name); - // - Disable expectation of type parameters - //imp.data.resolve(crate, false); - } - - // TODO: All other types - for(auto& item : mod.items()) { - if( item.data.is_Function() ) { - SetCrateName_Type(crate, name, item.data.as_Function().rettype()); - } - } -} - - -// First pass of conversion -// - Tag paths of external crate items with crate name -// - Convert all paths into absolute paths (or local variable references) -void ResolvePaths(AST::Crate& crate) -{ - DEBUG(" >>>"); - // Pre-process external crates to tag all paths - #if 0 - DEBUG(" --- Extern crates"); - INDENT(); - for(auto& ec : crate.extern_crates()) - { - SetCrateName_Mod(crate, ec.first, ec.second.root_module()); - } - UNINDENT(); - #endif - - // Handle 'use' statements in an initial parss - DEBUG(" --- Use Statements"); - INDENT(); - ResolvePaths_HandleModule_Use(crate, AST::Path("", {}), crate.root_module()); - UNINDENT(); - - // Resolve traits next, to ensure they're usable - //ResolvePaths_HandleModule_Trait(crate, AST::Path("", {}), crate.root_module()); - // Resolve impl block headers - //ResolvePaths_HandleModule_Impl(crate, AST::Path("", {}), crate.root_module()); - - // Then do path resolution on all other items - CPathResolver pr(crate); - DEBUG(" ---"); - pr.handle_module(AST::Path("", {}), crate.root_module()); - DEBUG(" <<<"); - - pr.m_second_pass = true; - DEBUG(" ---"); - pr.handle_module(AST::Path("", {}), crate.root_module()); - DEBUG(" <<<"); -} diff --git a/src/convert/typecheck_bounds.cpp b/src/convert/typecheck_bounds.cpp deleted file mode 100644 index f2cda828..00000000 --- a/src/convert/typecheck_bounds.cpp +++ /dev/null @@ -1,58 +0,0 @@ -/* - */ -#include -#include "ast_iterate.hpp" -#include "../ast/crate.hpp" -#include "../common.hpp" -#include - -class CGenericBoundChecker: - public CASTIterator -{ - void check_is_trait(const AST::Path& trait) const; -public: - virtual void handle_expr(AST::ExprNode& root) override; - virtual void handle_params(AST::GenericParams& params) override; -}; - -void CGenericBoundChecker::handle_expr(AST::ExprNode& root) -{ - // Do nothing (this iterator shouldn't recurse into expressions) -} - -void CGenericBoundChecker::check_is_trait(const AST::Path& trait) const { - assert( !trait.binding().is_Unbound() ); - DEBUG("trait = " << trait); - if( trait.binding().is_Trait() ) - { - //throw CompileError::BoundNotTrait( bound.lex_scope(), bound.param(), trait ); - throw ::std::runtime_error(FMT("TODO - Bound " << trait << " not a trait : " << trait.binding())); - } - else { - DEBUG("Bound is a trait, good"); - } -} - -void CGenericBoundChecker::handle_params(AST::GenericParams& params) -{ - for(auto& bound : params.bounds()) - { - TU_MATCH(AST::GenericBound, (bound), (ent), - (Lifetime, {}), - (TypeLifetime, {}), - (IsTrait, this->check_is_trait(ent.trait);), - (MaybeTrait, this->check_is_trait(ent.trait);), - (NotTrait, this->check_is_trait(ent.trait);), - (Equality, {}) - ) - } -} - -/// Typecheck generic bounds (where clauses) -void Typecheck_GenericBounds(AST::Crate& crate) -{ - DEBUG(" --- "); - CGenericBoundChecker chk; - chk.handle_module(AST::Path("", {}), crate.root_module()); -} - diff --git a/src/convert/typecheck_expr.cpp b/src/convert/typecheck_expr.cpp deleted file mode 100644 index 59e9a4aa..00000000 --- a/src/convert/typecheck_expr.cpp +++ /dev/null @@ -1,609 +0,0 @@ -/* - * MRustC - Mutabah's Rust Compiler - * - By John Hodge (Mutabah/thePowersGang) - * - * convert/typecheck_expr.cpp - * - Handles type checking, expansion, and method resolution for expressions (function bodies) - */ -#include -#include "ast_iterate.hpp" -#include "../ast/expr.hpp" -#include "../ast/crate.hpp" -#include "../common.hpp" -#include - -// === PROTOTYPES === -class CTypeChecker: - public CASTIterator -{ - friend class CTC_NodeVisitor; - - struct Scope { - ::std::vector< ::std::tuple > vars; - ::std::vector< ::std::tuple< ::std::string, TypeRef> > types; - ::std::map< ::std::string, TypeRef > params; - ::std::vector< AST::Path > traits; - }; - - AST::Crate& m_crate; - ::std::vector m_scopes; - -public: - CTypeChecker(AST::Crate& crate): - m_crate(crate) - {} - - virtual void start_scope() override; - virtual void local_variable(bool is_mut, ::std::string name, const TypeRef& type) override; - virtual void local_type(::std::string name, TypeRef type) override; - virtual void end_scope() override; - - virtual void handle_params(AST::GenericParams& params) override; - - virtual void handle_pattern_enum( - ::std::vector& pat_args, const ::std::vector& hint_args, - const AST::GenericParams& enum_params, const AST::EnumVariant& var, - ::std::vector& sub_patterns - ) override; - - virtual void handle_function(AST::Path path, AST::Function& fcn) override; - // - Ignore all non-function items on this pass - virtual void handle_enum(AST::Path path, AST::Enum& ) override {} - virtual void handle_struct(AST::Path path, AST::Struct& str) override {} - virtual void handle_alias(AST::Path path, AST::TypeAlias& ) override {} - -private: - TypeRef& get_local_var(const char* name); - const TypeRef& get_local_type(const char* name); - const TypeRef& get_type_param(const char* name); - - void check_enum_variant( - ::std::vector& path_args, const ::std::vector& argtypes, - const AST::GenericParams& params, const AST::EnumVariant& var - ); - void iterate_traits(::std::function fcn); -}; -class CTC_NodeVisitor: - public AST::NodeVisitorDef -{ - CTypeChecker& m_tc; -public: - CTC_NodeVisitor(CTypeChecker& tc): - m_tc(tc) - {} - - virtual void visit(AST::ExprNode_NamedValue& node) override; - - virtual void visit(AST::ExprNode_LetBinding& node) override; - virtual void visit(AST::ExprNode_Assign& node) override; - - virtual void visit(AST::ExprNode_Match& node) override; - - virtual void visit(AST::ExprNode_Field& node) override; - virtual void visit(AST::ExprNode_Cast& node) override; - - virtual void visit(AST::ExprNode_CallMethod& node) override; - virtual void visit(AST::ExprNode_CallPath& node) override; -}; - -void CTypeChecker::start_scope() -{ - m_scopes.push_back( Scope() ); -} -void CTypeChecker::local_variable(bool is_mut, ::std::string name, const TypeRef& type) -{ - DEBUG("is_mut=" << is_mut << " name=" << name << " type=" << type); - m_scopes.back().vars.push_back( make_tuple(is_mut, name, TypeRef(type)) ); -} -void CTypeChecker::local_type(::std::string name, TypeRef type) -{ - DEBUG("name=" << name << " type=" << type); - m_scopes.back().types.push_back( make_tuple(name, ::std::move(type)) ); -} -void CTypeChecker::end_scope() -{ - m_scopes.pop_back(); -} - -void CTypeChecker::handle_params(AST::GenericParams& params) -{ - ::std::map trs; - - for( const auto& param : params.ty_params() ) - { - trs.insert( make_pair(param.name(), TypeRef()) ); - } - - for( const auto& bound : params.bounds() ) - { - if( bound.is_IsTrait() && bound.as_IsTrait().type.is_type_param() ) - { - const auto& name = bound.as_IsTrait().type.type_param(); - int i = params.find_name(name.c_str()); - assert(i >= 0); - // - Just assert that it's valid. - //trs[name].add_trait( bound.bound() ); - } - } - - assert(m_scopes.back().params.size() == 0); - m_scopes.back().params = trs; -} -void CTypeChecker::handle_pattern_enum( - ::std::vector& pat_args, const ::std::vector& hint_args, - const AST::GenericParams& enum_params, const AST::EnumVariant& var, - ::std::vector& sub_patterns - ) -{ - #if 0 - check_enum_variant(pat_args, hint_args, enum_params, var); - - // Ensure that sub_patterns is the same length as the variant - const auto& var_types = var.m_sub_types; - if( sub_patterns.size() != var_types.size() ) - throw ::std::runtime_error(FMT("Enum pattern size mismatch")); - for( unsigned int i = 0; i < sub_patterns.size(); i ++ ) - { - // TODO: Need to propagate types through here correctly. - // - hint_args -> enum -> this - TypeRef arg = var_types[i]; - arg.resolve_args([&](const char *name){ - int i = enum_params.find_name(name); - if(i < 0) throw ""; - return hint_args[i]; - }); - handle_pattern(sub_patterns[i], var_types[i]); - } - #else - throw ::std::runtime_error("TODO: CTypeChecker::handle_pattern_enum "); - #endif -} - -TypeRef& CTypeChecker::get_local_var(const char* name) -{ - for( auto it = m_scopes.end(); it-- != m_scopes.begin(); ) - { - for( auto it2 = it->vars.end(); it2-- != it->vars.begin(); ) - { - if( name == ::std::get<1>(*it2) ) - { - return ::std::get<2>(*it2); - } - } - } - throw ::std::runtime_error(FMT("get_local_var - name " << name << " not found")); -} -const TypeRef& CTypeChecker::get_local_type(const char* name) -{ - for( auto it = m_scopes.end(); it-- != m_scopes.begin(); ) - { - for( auto it2 = it->types.end(); it2-- != it->types.begin(); ) - { - if( name == ::std::get<0>(*it2) ) - { - return ::std::get<1>(*it2); - } - } - } - throw ::std::runtime_error(FMT("get_local_type - name " << name << " not found")); -} -const TypeRef& CTypeChecker::get_type_param(const char* name) -{ - DEBUG("name = " << name); - for( auto it = m_scopes.end(); it-- != m_scopes.begin(); ) - { - DEBUG("- params = " << it->params); - auto ent = it->params.find(name); - if( ent != it->params.end() ) - { - DEBUG("> match " << ent->second); - return ent->second; - } - } - throw ::std::runtime_error(FMT("get_type_param - name " << name << " not found")); -} - -void CTypeChecker::handle_function(AST::Path path, AST::Function& fcn) -{ - DEBUG("(path = " << path << ")"); - start_scope(); - - handle_params(fcn.params()); - - handle_type(fcn.rettype()); - - for( auto& arg : fcn.args() ) - { - handle_type(arg.second); - handle_pattern( arg.first, arg.second ); - } - - CTC_NodeVisitor nv(*this); - if( fcn.code().is_valid() ) - { - fcn.code().node().get_res_type() = fcn.rettype(); - fcn.code().visit_nodes(nv); - } - - end_scope(); -} - -void CTypeChecker::iterate_traits(::std::function fcn) -{ - for( auto scopei = m_scopes.end(); scopei-- != m_scopes.begin(); ) - { - for( auto& trait : scopei->traits ) - { - if( !fcn(TypeRef(Span(), trait)) ) - { - return; - } - } - } -} - -void CTypeChecker::check_enum_variant(::std::vector& path_args, const ::std::vector& argtypes, const AST::GenericParams& params, const AST::EnumVariant& var) -{ - #if 0 - // We know the enum, but it might have type params, need to handle that case - // TODO: Check for more parameters than required - if( params.ty_params().size() > 0 ) - { - // 1. Obtain the pattern set from the path (should it be pre-marked with _ types?) - while( path_args.size() < params.ty_params().size() ) - path_args.push_back( TypeRef() ); - DEBUG("path_args = [" << path_args << "]"); - // 2. Create a pattern from the argument types and the format of the variant - DEBUG("argtypes = [" << argtypes << "]"); - ::std::vector item_args(params.ty_params().size()); - DEBUG("variant type = " << var.m_sub_types << ""); - for( unsigned int i = 0; i < var.m_sub_types.size(); i ++ ) - { - var.m_sub_types[i].match_args( - TypeRef(TypeRef::TagTuple(), Span(), argtypes), - [&](const char *name, const TypeRef& t) { - DEBUG("Binding " << name << " to type " << t); - int idx = params.find_name(name); - if( idx == -1 ) { - throw ::std::runtime_error(FMT("Can't find generic " << name)); - } - item_args.at(idx).merge_with( t ); - } - ); - } - DEBUG("item_args = [" << item_args << "]"); - // 3. Merge the two sets of arguments - for( unsigned int i = 0; i < path_args.size(); i ++ ) - { - path_args[i].merge_with( item_args[i] ); - } - DEBUG("new path_args = [" << path_args << "]"); - } - #else - throw ::std::runtime_error("TODO: CTypeChecker::check_enum_variant"); - #endif -} - -/// Named value - leaf -void CTC_NodeVisitor::visit(AST::ExprNode_NamedValue& node) -{ - DEBUG("ExprNode_NamedValue - " << node.m_path); - const AST::Path& p = node.m_path; - if( p.is_absolute() ) - { - // grab bound item - TU_MATCH_DEF(AST::PathBinding, (p.binding()), (info), - ( - throw ::std::runtime_error( FMT("Unknown binding type on named value : "<type(); - ), - (EnumVar, - const AST::Enum& enm = *info.enum_; - auto idx = info.idx; - // Enum variant: - // - Check that this variant takes no arguments - if( ! enm.variants()[idx].m_data.is_Value() ) - throw ::std::runtime_error( "Used a non-unit variant as a raw value" ); - // - Set output type to the enum (wildcard params, not default) - AST::Path tp = p; - tp.nodes().pop_back(); - AST::PathNode& pn = tp.nodes().back(); - unsigned int num_params = enm.params().ty_params().size(); - if(pn.args().size() > num_params) - throw ::std::runtime_error( FMT("Too many arguments to enum variant - " << p) ); - while(pn.args().size() < num_params) - pn.args().push_back( TypeRef() ); - node.get_res_type() = TypeRef(Span(node.get_pos()), tp); - ) - ) - } - else - { - TypeRef& local_type = m_tc.get_local_var( p[0].name().c_str() ); - node.get_res_type().merge_with( local_type ); - DEBUG("res type = " << node.get_res_type()); - local_type = node.get_res_type(); - } -} - -void CTC_NodeVisitor::visit(AST::ExprNode_LetBinding& node) -{ - DEBUG("ExprNode_LetBinding"); - - node.get_res_type() = TypeRef(TypeRef::TagUnit(), Span(node.get_pos())); - - // Evaluate value - AST::NodeVisitor::visit(node.m_value); - - const TypeRef& bind_type = node.m_type; - const TypeRef& val_type = node.m_value->get_res_type(); - - // Obtain resultant type from value - // Compare to binding type - // - If both concrete, but different : error - if( bind_type.is_concrete() && val_type.is_concrete() ) - { - if( bind_type != val_type ) { - throw ::std::runtime_error( FMT("Type mismatch on let, expected " << bind_type << ", got " << val_type) ); - } - } - // - If neither concrete, merge requirements of both - else - { - node.m_type.merge_with( val_type ); - node.m_value->get_res_type() = node.m_type; - } - - m_tc.handle_pattern(node.m_pat, node.m_type); -} - -void CTC_NodeVisitor::visit(AST::ExprNode_Assign& node) -{ - node.get_res_type() = TypeRef(TypeRef::TagUnit(), Span(node.get_pos())); - AST::NodeVisitor::visit(node.m_slot); - AST::NodeVisitor::visit(node.m_value); -} - -void CTC_NodeVisitor::visit(AST::ExprNode_Match& node) -{ - DEBUG("ExprNode_Match"); - AST::NodeVisitor::visit(node.m_val); - - for( auto& arm : node.m_arms ) - { - m_tc.start_scope(); - for( auto& pat : arm.m_patterns ) - m_tc.handle_pattern(pat, node.m_val->get_res_type()); - AST::NodeVisitor::visit(arm.m_cond); - AST::NodeVisitor::visit(arm.m_code); - m_tc.end_scope(); - } -} - -void CTC_NodeVisitor::visit(AST::ExprNode_Field& node) -{ - DEBUG("ExprNode_Field " << node.m_name); - - AST::NodeVisitor::visit(node.m_obj); - - TypeRef* tr = &node.m_obj->get_res_type(); - DEBUG("ExprNode_Field - tr = " << *tr); - if( tr->is_concrete() ) - { - // Must be a structure type (what about associated items?) - unsigned int deref_count = 0; - while( tr->is_reference() ) - { - tr = &tr->inner_type(); - DEBUG("ExprNode_Field - ref deref to " << *tr); - deref_count ++; - } - if( !tr->is_path() ) - { - throw ::std::runtime_error("ExprNode_Field - Type not a path"); - } - - // TODO Move this logic to types.cpp? - const AST::Path& p = tr->path(); - TU_MATCH_DEF( AST::PathBinding, (p.binding()), (info), - ( - throw ::std::runtime_error("TODO: Get field from non-structure"); - ), - (Struct, - const AST::PathNode& lastnode = p.nodes().back(); - AST::Struct& s = const_cast( *info.struct_ ); - node.get_res_type().merge_with( s.get_field_type(node.m_name.c_str(), lastnode.args()) ); - ) - ) - DEBUG("deref_count = " << deref_count); - for( unsigned i = 0; i < deref_count; i ++ ) - { - node.m_obj = ::std::unique_ptr(new AST::ExprNode_Deref( ::std::move(node.m_obj) )); - } - } - else - { - DEBUG("ExprNode_Field - Type not concrete, can't get field"); - } -} - -void CTC_NodeVisitor::visit(AST::ExprNode_Cast& node) -{ - DEBUG("ExprNode_Cast " << node.m_type); - - AST::NodeVisitor::visit(node.m_value); - - node.get_res_type().merge_with( node.m_type ); -} - -void CTC_NodeVisitor::visit(AST::ExprNode_CallMethod& node) -{ - DEBUG("ExprNode_CallMethod " << node.m_method); - - AST::NodeVisitor::visit(node.m_val); - - for( auto& arg : node.m_args ) - { - AST::NodeVisitor::visit(arg); - } - - // Locate method - const TypeRef& type = node.m_val->get_res_type(); - DEBUG("CallMethod - type = " << type); - - // Replace generic references in 'type' (copying the type) with - // '_: Bounds' (allowing method lookup to succeed) - TypeRef ltype = type; - unsigned int deref_count = 0; - ltype.resolve_args( [&](const char* name) { - return m_tc.get_type_param(name); - } ); - - // Begin trying options (attempting an autoderef each time) - const char * const name = node.m_method.name().c_str(); - AST::Function* fcnp = nullptr; - do - { - // 1. Handle bounded wildcard types - if( ltype.is_wildcard() ) - { - throw ::std::runtime_error("TODO: _ in CallMethod"); - //if( ltype.traits().size() == 0 ) { - // DEBUG("- Unconstrained wildcard, returning"); - // return ; - //} - // - //for( const auto& t : ltype.traits() ) - //{ - // DEBUG("- Trait " << t.path()); - // AST::Trait& trait = const_cast( t.path().binding().bound_trait() ); - // // - Find method on one of them - // for( auto& m : trait.functions() ) - // { - // DEBUG(" > method: " << m.name << " search: " << node.m_method.name()); - // if( m.name == node.m_method.name() ) - // { - // DEBUG(" > Found method"); - // fcnp = &m.data; - // break; - // } - // } - // if(fcnp) break; - //} - //if(fcnp) break; - } - else - { - // 2. Find inherent impl - auto oimpl = m_tc.m_crate.get_impl(AST::Path(), ltype); - if( oimpl.is_some() ) - { - AST::Impl& impl = oimpl.unwrap(); - // 1.1. Search impl for this method - for(auto& i : impl.items()) - { - if( i.name == name && i.data.is_Function() ) - { - fcnp = &i.data.as_Function(); - break; - } - } - if(fcnp) break; - } - - // 2. Iterate in-scope traits - m_tc.iterate_traits( [&](const TypeRef& trait) { - // TODO: Check trait first, then find an impl - auto oimpl = m_tc.m_crate.get_impl(trait.path(), ltype); - if( oimpl.is_some() ) - { - AST::Impl& impl = oimpl.unwrap(); - for(auto& i : impl.items()) - { - if( i.name == name && i.data.is_Function() ) - { - fcnp = &i.data.as_Function(); - break; - } - } - } - return fcnp == nullptr; - }); - } - if( fcnp ) - break; - deref_count ++; - } while( ltype.deref(true) ); - - if( fcnp ) - { - DEBUG("deref_count = " << deref_count); - for( unsigned i = 0; i < deref_count; i ++ ) - { - node.m_val = ::std::unique_ptr(new AST::ExprNode_Deref( ::std::move(node.m_val) )); - } - - AST::Function& fcn = *fcnp; - if( fcn.params().ty_params().size() != node.m_method.args().size() ) - { - throw ::std::runtime_error("CallMethod with param count mismatch"); - } - if( fcn.params().ty_params().size() ) - { - throw ::std::runtime_error("TODO: CallMethod with params"); - } - node.get_res_type().merge_with( fcn.rettype() ); - } -} -void CTC_NodeVisitor::visit(AST::ExprNode_CallPath& node) -{ - DEBUG("ExprNode_CallPath - " << node.m_path); - ::std::vector argtypes; - for( auto& arg : node.m_args ) - { - AST::NodeVisitor::visit(arg); - argtypes.push_back( arg->get_res_type() ); - } - - TU_MATCH_DEF( AST::PathBinding, (node.m_path.binding()), (info), - ( - throw ::std::runtime_error("CallPath on non-function"); - ), - (Function, - const AST::Function& fcn = *info.func_; - - if( fcn.params().ty_params().size() > 0 ) - { - throw ::std::runtime_error("CallPath - TODO: Params on functions"); - } - - DEBUG("ExprNode_CallPath - rt = " << fcn.rettype()); - node.get_res_type().merge_with( fcn.rettype() ); - ), - (EnumVar, - const AST::Enum& enm = *info.enum_; - const unsigned int idx = info.idx; - - auto& path_node_enum = node.m_path[node.m_path.size()-2]; - m_tc.check_enum_variant(path_node_enum.args(), argtypes, enm.params(), enm.variants().at(idx)); - - AST::Path p = node.m_path; - p.nodes().pop_back(); - TypeRef ty(Span(), ::std::move(p) ); - - DEBUG("ExprNode_CallPath - enum t = " << ty); - node.get_res_type().merge_with(ty); - ) - ) -} - -void Typecheck_Expr(AST::Crate& crate) -{ - DEBUG(" >>>"); - CTypeChecker tc(crate); - tc.handle_module(AST::Path("", {}), crate.root_module()); - DEBUG(" <<<"); -} - diff --git a/src/convert/typecheck_params.cpp b/src/convert/typecheck_params.cpp deleted file mode 100644 index aa53d3bd..00000000 --- a/src/convert/typecheck_params.cpp +++ /dev/null @@ -1,344 +0,0 @@ -/* -/// Typecheck generic parameters (ensure that they match all generic bounds) - */ -#include -#include "ast_iterate.hpp" -#include "../ast/crate.hpp" -#include "../common.hpp" -#include - -// === PROTOTYPES === -class CGenericParamChecker: - public CASTIterator -{ - int m_within_expr = 0; - struct LocalType { - const ::std::string name; - const AST::GenericParams* source_params; // if nullptr, use fixed_type - TypeRef fixed_type; - - LocalType(): - name("") - {} - LocalType(const ::std::string& n, const AST::GenericParams* tps): - name(n), source_params(tps) - {} - LocalType(const ::std::string& n, TypeRef ty): - name(n), source_params(nullptr), fixed_type( ::std::move(ty) ) - {} - - bool is_separator() const { return name == ""; } - }; - // name == "" indicates edge of a scope - ::std::vector m_types_stack; - - AST::Crate& m_crate; -public: - CGenericParamChecker(AST::Crate& c): - m_crate(c) - { - } - - virtual void handle_path(AST::Path& path, CASTIterator::PathMode pm) override; - virtual void handle_expr(AST::ExprNode& root) override; - void start_scope() override; - void local_type(::std::string name, TypeRef type) override; - void end_scope() override; - virtual void handle_params(AST::GenericParams& params) override; - -private: - bool has_impl_for_param(const ::std::string name, const AST::Path& trait) const; - bool has_impl(const TypeRef& type, const AST::Path& trait) const; - void check_generic_params(const AST::GenericParams& info, ::std::vector& types, TypeRef self_type, bool allow_infer = false); - - const LocalType* find_type_by_name(const ::std::string& name) const; -}; - -class CNodeVisitor: - public AST::NodeVisitorDef -{ - CGenericParamChecker& m_pc; -public: - CNodeVisitor(CGenericParamChecker& pc): - m_pc(pc) - {} -}; - -// === CODE === -bool CGenericParamChecker::has_impl_for_param(const ::std::string name, const AST::Path& trait) const -{ - TRACE_FUNCTION_F("name = " << name << ", trait = " << trait); - - if( m_crate.is_trait_implicit(trait) ) - return true; - - const AST::GenericParams* tps = nullptr; - // Locate params set that contains the passed name - for( const auto lt : m_types_stack ) - { - if( lt.name == name ) - { - if( lt.source_params != nullptr ) { - tps = lt.source_params; - } - else { - DEBUG("Type name '" << name << "' isn't a param"); - return has_impl(lt.fixed_type, trait); - } - //break ; - } - } - - if( !tps ) - { - throw ::std::runtime_error(FMT("Param '"<bounds() ) - { - DEBUG("bound = " << bound); - TU_IFLET( AST::GenericBound, bound, IsTrait, ent, - if( ent.type.is_type_param() && ent.type.type_param() == name ) - { - DEBUG("bound.type() {" << ent.trait << "} == trait {" << trait << "}"); - if( ent.trait == trait ) - return true; - } - ) - } - - // TODO: Search for generic ("impl Trait1 for T") that fits bounds - - DEBUG("No match in generics, returning failure"); - return false; -} - -bool CGenericParamChecker::has_impl(const TypeRef& type, const AST::Path& trait) const -{ - TRACE_FUNCTION_F("type = " << type << ", trait = " << trait); - if( type.is_type_param() ) - { - // TODO: Search current scope (requires access to CGenericParamChecker) for this type, - // and search the bounds for this trait - // - Also accept bounded generic impls (somehow) - { - return true; - } - } - else - { - // Search all known impls of this trait (TODO: keep a list at the crate level) for a match to this type - if( m_crate.find_impl(trait, type, nullptr, nullptr) == false ) { - DEBUG("- Nope"); - return false; - } - - return true; - } - return false; -} - -/// Check that the passed set of parameters match the requiremens for a generic item -/// -/// \param info Generic item information (param names and bounds) -/// \param types Type parameters being passed to the generic item -/// \param allow_infer Allow inferrence (mutates \a types with conditions from \a info) -void CGenericParamChecker::check_generic_params(const AST::GenericParams& info, ::std::vector& types, TypeRef self_type, bool allow_infer) -{ - TRACE_FUNCTION_F("info = " << info << ", types = {" << types << "}"); - // TODO: Need to correctly handle lifetime params here, they should be in a different list - const auto& params = info.ty_params(); - - if( types.size() > params.size() ) - { - throw ::std::runtime_error(FMT("Too many generic params ("<fixed_type; - check_generic_params(params, last_node.args(), self_type, (m_within_expr > 0)); - }; - - TU_MATCH( AST::PathBinding, (path.binding()), (info), - (Unbound, - throw CompileError::BugCheck( FMT("CGenericParamChecker::handle_path - Unbound path : " << path) ); - ), - (Module, - DEBUG("WTF - Module path, isn't this invalid at this stage?"); - ), - (Trait, - comm( info.trait_->params() ); - ), - (Struct, - comm( info.struct_->params() ); - ), - (Enum, - comm( info.enum_->params() ); - ), - (TypeAlias, - comm( info.alias_->params() ); - ), - (Function, - check_generic_params(info.func_->params(), last_node.args(), TypeRef(TypeRef::TagInvalid(), Span()), (m_within_expr > 0)); - ), - - (EnumVar, - throw ::std::runtime_error("TODO: handle_path EnumVar"); - ), - (Static, - throw ::std::runtime_error("TODO: handle_path Static"); - ), - (StructMethod, - throw ::std::runtime_error("TODO: handle_path StructMethod"); - ), - (TraitMethod, - throw ::std::runtime_error("TODO: handle_path TraitMethod"); - ), - (TypeParameter, - throw ::std::runtime_error("TODO: handle_path TypeParameter"); - ), - (Variable, - throw ::std::runtime_error("TODO: handle_path Variable"); - ) - ) -} - -void CGenericParamChecker::handle_expr(AST::ExprNode& root) -{ - m_within_expr += 1; - // Do nothing (this iterator shouldn't recurse into expressions) - CNodeVisitor nv(*this); - root.visit(nv); - m_within_expr -= 1; -} - -void CGenericParamChecker::start_scope() -{ - m_types_stack.push_back( LocalType() ); -} -void CGenericParamChecker::local_type(::std::string name, TypeRef type) -{ - DEBUG("name = " << name << ", type = " << type); - m_types_stack.push_back( LocalType(::std::move(name), ::std::move(type)) ); -} -void CGenericParamChecker::end_scope() -{ - assert( m_types_stack.size() > 0 ); - while( !m_types_stack.back().is_separator() ) - m_types_stack.pop_back(); - // pop the separator - m_types_stack.pop_back(); -} -void CGenericParamChecker::handle_params(AST::GenericParams& params) -{ - DEBUG("params = " << params); - for( const auto& p : params.ty_params()) - m_types_stack.push_back( LocalType(p.name(), ¶ms) ); -} - -const CGenericParamChecker::LocalType* CGenericParamChecker::find_type_by_name(const ::std::string& name) const -{ - for( unsigned int i = m_types_stack.size(); i --; ) - { - if( m_types_stack[i].name == name ) - return &m_types_stack[i]; - } - return nullptr; -} - -/// Typecheck generic parameters (ensure that they match all generic bounds) -void Typecheck_GenericParams(AST::Crate& crate) -{ - DEBUG(" >>> "); - CGenericParamChecker chk(crate); - chk.handle_module(AST::Path("", {}), crate.root_module()); - DEBUG(" <<< "); -} - diff --git a/src/main.cpp b/src/main.cpp index b6dd9254..963491d5 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -69,9 +69,6 @@ void CompilePhaseV(const char *name, Fcn f) { /// main! int main(int argc, char *argv[]) { - AST_InitProvidedModule(); - - ProgramParams params(argc, argv); // Set up cfg values @@ -104,11 +101,6 @@ int main(int argc, char *argv[]) CompilePhaseV("Expand", [&]() { Expand(crate); }); - - // Run a quick post-parse pass - CompilePhaseV("PostParse", [&]() { - crate.index_impls(); - }); // XXX: Dump crate before resolve CompilePhaseV("Temp output - Parsed", [&]() { -- cgit v1.2.3